Introduction
In this notebook we demonstrate how to use Milo to detect abherrant cell states in diseased tissues, using a dataset of hepatic non-parenchymal cells isolated from 5 healthy and 5 cirrhotic human livers. Ramachandran et al. 2019 (GEO accessiion: GSE136103).
suppressPackageStartupMessages({
library(tidyverse)
library(irlba)
library(DropletUtils)
library(scater)
library(scran)
library(Seurat) ## just 4 loading the object
library(miloR)
library(SingleCellExperiment)
library(patchwork)
library(igraph)
library(RColorBrewer)
library(cowplot)
})
Load data
We downloaded the dataset and annotations stored in Seurat object from here, as indicated by the authors.
load("/nfs/team205/ed6/data/Ramachandran2019_liver/tissue.rdata")
## Convert to SingleCellExperiment
liver_sce <- SingleCellExperiment(assay = list(counts=tissue@raw.data, logcounts=tissue@data),
colData = tissue@meta.data)
liver_sce
class: SingleCellExperiment
dim: 23498 58358
metadata(0):
assays(2): counts logcounts
rownames(23498): FO538757.2 AP006222.2 ... CTA-126B4.7 LINC01423
rowData names(0):
colnames(58358): Healthy1_Cd45+_AAACCTGCAGTATCTG
Healthy1_Cd45+_AACTGGTTCATGGTCA ...
Cirrhotic3_Cd45-_TTTGTCATCCAGGGCT
Cirrhotic3_Cd45-_TCTGGAAGTCATCCCT
colData names(10): nGene nUMI ... annotation_indepth
annotation_lineage
reducedDimNames(0):
spikeNames(0):
altExpNames(0):
Preprocessing
Feature selection
dec_liver <- modelGeneVar(liver_sce)
fit_liver <- metadata(dec_liver)
plot(fit_liver$mean, fit_liver$var, xlab="Mean of log-expression",
ylab="Variance of log-expression")

hvgs <- getTopHVGs(dec_liver, n=3000)
Dimensionality reduction with PCA
liver_sce <- runPCA(liver_sce, subset_row=hvgs, ncomponents=11)
plotPCA(liver_sce, colour_by="condition", ncomponents=3)

liver_sce <- runUMAP(liver_sce, dimred="PCA", ncomponents=2)
scater::plotUMAP(liver_sce, colour_by="condition", point_alpha=1, point_size=0.5)

scater::plotUMAP(liver_sce, colour_by="dataset", point_alpha=0.3, point_size=0.5)

scater::plotUMAP(liver_sce, colour_by="annotation_lineage", point_alpha=0.3, point_size=0.5, text_by='annotation_lineage')

# scater::plotUMAP(liver_sce, colour_by='annotation_indepth', point_alpha=0.3, point_size=0.5, text_by='annotation_indepth')
Notably, this dataset doesn’t appear to display a batch effect
DA analysis with Milo
We test for differential abundance between healthy and cirrhotic livers. We start by defining neighbourhoods with refined sampling on the KNN graph. We inspect the size of neighbourhoods.
liver_milo <- Milo(liver_sce)
## Build KNN graph
liver_milo <- buildGraph(liver_milo, d = 11, k=30)
Constructing kNN graph with k:30
## Compute neighbourhoods with refined sampling
liver_milo <- makeNhoods(liver_milo, k=30, d=11, prop = 0.05, refined=TRUE)
Checking valid object
plotNhoodSizeHist(liver_milo, bins=150)

Then we make a design matrix for the differential test, assigning samples to conditions.
liver_meta <- as.tibble(colData(liver_milo)[,c("dataset","condition")])
`as.tibble()` is deprecated as of tibble 2.0.0.
Please use `as_tibble()` instead.
The signature and semantics have changed, see `?as_tibble`.
[90mThis warning is displayed once every 8 hours.[39m
[90mCall `lifecycle::last_warnings()` to see where this warning was generated.[39m
liver_meta <- distinct(liver_meta) %>%
mutate(condition=factor(condition, levels=c("Uninjured", "Cirrhotic"))) %>%
column_to_rownames("dataset")
Now we can count cells in neighbourhoods and perform the DA test.
liver_milo <- countCells(liver_milo, samples = "dataset", meta.data = data.frame(colData(liver_milo)[,c("dataset","condition")]) )
Checking meta.data validity
Setting up matrix with 2717 neighbourhoods
Counting cells in neighbourhoods
liver_milo <- calcNhoodDistance(liver_milo, d=11)
milo_res <- testNhoods(liver_milo, design = ~ condition, design.df = liver_meta, fdr.weighting = "k-distance")
Performing spatial FDR correction withk-distance weighting
Exploration of DA results
We can start by looking at some basic stats
pval_hist <- milo_res %>%
ggplot(aes(PValue)) +
geom_histogram(bins=50) +
theme_bw(base_size=14)
volcano <-
milo_res %>%
ggplot(aes(logFC, -log10(SpatialFDR))) +
geom_point(size=0.4, alpha=0.2) +
geom_hline(yintercept = -log10(0.1)) +
xlab("log-Fold Change") +
theme_bw(base_size=14)
pval_hist + volcano

The distribution of P-values looks sensible and from the volcano plot we can see that we have identified some DA neighbourhoods at 10% FDR. We can visualize DA neighbourhoods building an abstracted graph
liver_milo <- buildNhoodGraph(liver_milo)
Calculating nhood adjacency
\
Error: unexpected input in "\"
## Save milo object and results
# saveRDS(liver_milo,"/nfs/team205/ed6/data/Ramachandran2019_liver/tissue_milo.RDS")
saveRDS(liver_milo,"~/liver_milo_20201008.RDS")
# write_csv(milo_res, "/nfs/team205/ed6/data/Ramachandran2019_liver/milo_results.csv")
write_csv(milo_res,"/nfs/team205/ed6/data/Ramachandran2019_liver/liver_results_20201008.csv")
Parsed with column specification:
cols(
logFC = [32mcol_double()[39m,
logCPM = [32mcol_double()[39m,
F = [32mcol_double()[39m,
PValue = [32mcol_double()[39m,
FDR = [32mcol_double()[39m,
Nhood = [32mcol_double()[39m,
SpatialFDR = [32mcol_double()[39m
)
Making figures for the manuscript
colourCount = length(unique(liver_milo$annotation_lineage))
getPalette = colorRampPalette(brewer.pal(9, "Set2"))
n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
umap_df <- data.frame(reducedDim(liver_milo, "UMAP"))
colnames(umap_df) <- c("UMAP_1", "UMAP_2")
umap1 <- cbind(umap_df, annotation_lineage=liver_milo$annotation_lineage) %>%
ggplot(aes(UMAP_1, UMAP_2, color=as.character(annotation_lineage))) +
geom_point(size=0.1, alpha=0.5) +
ggrepel::geom_text_repel(data = . %>%
group_by(annotation_lineage) %>%
summarise(UMAP_1=mean(UMAP_1), UMAP_2=mean(UMAP_2)),
aes(label=annotation_lineage), color="black", size=6
) +
scale_color_manual(values=getPalette(colourCount)) +
guides(color="none") +
xlab("UMAP1") + ylab("UMAP2") +
coord_fixed() +
theme_classic(base_size = 22) +
theme(axis.text = element_blank(), axis.ticks = element_blank())
umap2 <-
cbind(umap_df, condition=as.character(liver_milo$condition)) %>%
ggplot(aes(UMAP_1, UMAP_2, color=condition)) +
geom_point(size=0.1, alpha=0.5) +
scale_color_brewer(palette="Set1", name='') +
xlab("UMAP1") + ylab("UMAP2") +
coord_fixed() +
guides(color='none') +
facet_wrap(condition~., ncol=1) +
theme_nothing(font_size = 22) +
theme(axis.text = element_blank(), axis.ticks = element_blank(), legend.position=c(0.9,0.9),
strip.background = element_rect(color=NA), strip.text = element_text(size=22))
nh_graph_pl <- plotNhoodGraphDA(liver_milo, milo_res, alpha = 0.1) +
theme(legend.text = element_text(size=22), legend.title = element_text(size=24)) +
coord_fixed()
invalid factor level, NA generatedinvalid factor level, NA generatedinvalid factor level, NA generatedinvalid factor level, NA generatedinvalid factor level, NA generatedinvalid factor level, NA generatedinvalid factor level, NA generated
fig4_top <- (umap1 | umap2 | nh_graph_pl) +
plot_layout(widths = c(3,1,3))
fig4_top +
ggsave("~/milo_output/liver_embedding.pdf", width=15, height = 10)

Next, we can check the cell types where we observe most differences between healthy and cirrhotic cells, by taking the most frequent cell type in each neighbourhood.
# Add annotation of most frequent cell type per nhood to milo results table
milo_res <- annotateNhoods(liver_milo, milo_res, "annotation_indepth")
anno_df <- data.frame(liver_milo@colData) %>%
distinct(annotation_lineage, annotation_indepth)
milo_res <- left_join(milo_res, anno_df, by="annotation_indepth")
We first check that neighbourhoods are quite homogeneous
frac_hist <- ggplot(milo_res, aes(annotation_indepth_fraction)) +
geom_histogram(bins=30) +
xlab("Fraction of cells in \nmost abundant cluster") +
ylab("# neighbourhoods") +
theme_bw(base_size=14)
frac_hist

I can recover all the clusters where DA was detected in the original paper (see all the barplots for each lineage) and more! All in a single analysis, and without knowing where the subclusters are. Let’s bear in mind that positive logFC
group.by = "annotation_indepth"
paper_DA <- list(cirrhotic=c("MPs (4)","MPs (5)",
"Endothelia (6)", "Endothelia (7)",
"Mes (3)",
"Tcells (2)",
"Myofibroblasts"
),
healthy=c("MPs (7)",
"Endothelia (1)",
"Tcells (1)", "Tcells (3)","Tcells (1)",
"ILCs (1)"
)
)
expDA_df <- bind_rows(
data.frame(annotation_indepth = paper_DA[["cirrhotic"]], pred_DA="cirrhotic"),
data.frame(annotation_indepth = paper_DA[["healthy"]], pred_DA="healthy")
)
pl1 <- milo_res %>%
left_join(expDA_df) %>%
mutate(is_signif = ifelse(SpatialFDR < 0.1, 1, 0)) %>%
mutate(logFC_color = ifelse(is_signif==1, logFC, NA)) %>%
arrange(annotation_lineage) %>%
mutate(Nhood=factor(Nhood, levels=unique(Nhood))) %>%
ggplot(aes(annotation_indepth, logFC, color=logFC_color)) +
scale_color_gradient2() +
guides(color="none") +
xlab(group.by) + ylab("Log Fold Change") +
ggbeeswarm::geom_quasirandom(alpha=1) +
coord_flip() +
facet_grid(annotation_lineage~., scales="free", space="free") +
theme_bw(base_size=22) +
theme(strip.text.y = element_text(angle=0),
axis.title.y = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank(),
)
Joining, by = "annotation_indepth"
pl2 <- milo_res %>%
left_join(expDA_df) %>%
# dplyr::filter(!is.na(pred_DA)) %>%
group_by(annotation_indepth) %>%
summarise(pred_DA=dplyr::first(pred_DA), annotation_lineage=dplyr::first(annotation_lineage)) %>%
mutate(end=ifelse(pred_DA=="healthy", 0, 1),
start=ifelse(pred_DA=="healthy", 1, 0)) %>%
ggplot(aes(annotation_indepth, start, xend = annotation_indepth, yend = end, color=pred_DA)) +
geom_segment(size=1,arrow=arrow(length = unit(0.1, "npc"), type="closed")) +
coord_flip() +
xlab("annotation") +
facet_grid(annotation_lineage~.,
# annotation_lineage~"Ramachandran et al.\nDA predictions",
scales="free", space="free") +
# guides(color="none") +
scale_color_brewer(palette="Set1", direction = -1,
labels=c("enriched in cirrhotic", "enriched in healthy"),
na.translate = F,
name="Ramachandran et al.\nDA predictions") +
guides(color=guide_legend(ncol = 1)) +
theme_bw(base_size=22) +
ylim(-0.1,1.1) +
theme(strip.text.y = element_blank(),strip.text.x = element_text(angle=90),
plot.margin = unit(c(0,0,0,0), "cm"), panel.grid = element_blank(),
axis.title.x = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(),
legend.position = "bottom")
Joining, by = "annotation_indepth"
`summarise()` ungrouping output (override with `.groups` argument)
fig4_bleft <- (pl2 + pl1 +
plot_layout(widths=c(1,10), guides = "collect") & theme(legend.position = 'top', legend.justification = 0))
fig4_bleft +
ggsave("~/milo_output/liver_DAcomparison.pdf", width=8, height = 13)

Close-up on Endothelial lineage
endo_milo <- scater::runUMAP(liver_milo[,liver_milo$annotation_lineage=="Endothelia"], dimred='PCA')
plotUMAP(endo_milo, colour_by = "annotation_indepth")

Filter out cells that show contamination from immune cells (expression of immune markers)
keep <- logcounts(endo_milo)["CD19",] == 0 | logcounts(endo_milo)["MS4A1",] == 0
endo_milo <- endo_milo[,keep]
endo_milo <- scater::runUMAP(endo_milo, dimred='PCA')
plotUMAP(endo_milo, colour_by = "annotation_indepth")

umap_df <- data.frame(reducedDim(endo_milo, "UMAP"))
colnames(umap_df) <- c("UMAP_1", "UMAP_2")
endo_umap <- cbind(umap_df, condition=endo_milo$condition) %>%
ggplot(aes(UMAP_1, UMAP_2, color=condition)) +
geom_point(size=0.3, alpha=0.5) +
scale_color_brewer(palette="Set1", name='') +
xlab("UMAP1") + ylab("UMAP2") +
coord_fixed() +
guides(color="none") +
facet_wrap(condition~., ncol=1) +
theme_nothing() +
theme(axis.text = element_blank(), axis.ticks = element_blank(), legend.position=c(0.9,0.9),
strip.background = element_rect(color=NA), strip.text = element_text(size=22))
liver_milo2 <- liver_milo
subset.nhoods <- str_detect(milo_res$annotation_indepth, "Endo")
reducedDim(liver_milo2, "UMAP")[colnames(endo_milo),] <- reducedDim(endo_milo, "UMAP")
endo_gr <-
plotNhoodGraphDA(
liver_milo2, milo_res,
subset.nhoods = subset.nhoods,
# ) =)[1:(length()-1)],
alpha = 0.1
) +
theme(legend.text = element_text(size=22), legend.title = element_text(size=24))
fig4_bright1 <- ((endo_umap + endo_gr ) +
plot_layout(widths = c(1,2),
guides = "collect"
))
fig4_bright1 +
ggsave("~/milo_output/liver_endoGraph.pdf", width=9, height = 5)

Differential expression between DA neighbourhoods
We merge overlapping nhoods with significant DA and the same direction of logFC, and then test for differential expression between cells in disease-specific and healthy-specific nhoods. This allows us to perform a comparison without further clustering.
Here we find markers grouping gene expression counts by sample (i.e. we don’t treat cells as replicates, but exploit the replication structure used also for DA testing)

x
class: Milo
dim: 23498 5883
metadata(0):
assays(2): counts logcounts
rownames(23498): FO538757.2 AP006222.2 ... CTA-126B4.7 LINC01423
rowData names(0):
colnames(5883): Healthy1_Cd45+_CCTCAGTTCCAAGTAC Healthy1_Cd45-A_TTCTCCTAGGGATGGG ... Cirrhotic3_Cd45-_TGTTCCGTCCAAACAC
Cirrhotic3_Cd45-_TCTGGAAGTCATCCCT
colData names(10): nGene nUMI ... annotation_indepth annotation_lineage
reducedDimNames(2): PCA UMAP
spikeNames(0):
altExpNames(0):
nhoods dimensions(1): 2717
nhoodCounts dimensions(2): 2717 20
nhoodDistances dimension(1): 2717
graph names(1): graph
nhoodIndex names(1): 2717
nhoodExpression dimension(2): 1 1
nhoodReducedDim names(0):
nhoodGraph names(1): nhoodGraph
nhoodAdjacency dimension(0):
Significant DGE genes (FDR 10%)
marker.df[marker.df$adj.P.Val_1 < 0.1,]
Visualize as volcano

Visualize as heatmap
(gene expression values are scaled between 0 and 1 for each gene)

GO term analysis
[1] "FCN3" "MS4A6A" "CRHBP" "CLEC4G" "FCN2" "CLEC1B" "CLEC4M" "ACP5" "LYVE1" "OIT3" "TFPI2" "MEG3" "STAB2" "FCGR2B"
[15] "BEX1" "BASP1" "ANPEP" "RELN" "LYPD2" "ECM1" "NPL" "MRO" "ACSM3" "SLC7A8" "PVALB" "EHD3"
em_res_up %>%
top_n(20, -log10(qvalue)) %>%
mutate(Term=factor(ID, levels=rev(unique(ID)))) %>%
ggplot(aes(Term, -log10(qvalue))) +
geom_point() +
coord_flip() +
xlab("GO Biological Function") + ylab("-log10(Adj. p-value)") +
theme_bw(base_size=14) +
ggtitle("Markers of cirrhotic")

em_res_down %>%
top_n(30, -log10(qvalue)) %>%
mutate(Term=factor(ID, levels=rev(unique(ID)))) %>%
ggplot(aes(Term, -log10(qvalue))) +
geom_point() +
coord_flip() +
xlab("GO Biological Function") + ylab("-log10(Adj. p-value)") +
theme_bw(base_size=14) +
ggtitle("Markers of healthy")

Full GO enrichment - up in cirrhotic
(geneID column indicates which genes belong to gene ontology)
em_res_up
Full GO enrichment - up in healty
(geneID column indicates which genes belong to gene ontology)
em_res_down
Close-up on Cholangiocytes
Filter out cells that show contamination from immune cells (expression of immune markers)

umap_df <- data.frame(reducedDim(chol_milo, "UMAP"))
colnames(umap_df) <- c("UMAP_1", "UMAP_2")
chol_umap <- cbind(umap_df, condition=chol_milo$condition) %>%
ggplot(aes(UMAP_1, UMAP_2, color=condition)) +
geom_point(size=0.3, alpha=0.5) +
scale_color_brewer(palette="Set1", name='') +
xlab("UMAP1") + ylab("UMAP2") +
coord_fixed() +
guides(color="none") +
facet_wrap(condition~., ncol=1) +
theme_nothing() +
theme(axis.text = element_blank(), axis.ticks = element_blank(), legend.position=c(0.9,0.9),
strip.background = element_rect(color=NA), strip.text = element_text(size=22))
chol_umap

liver_milo2 <- liver_milo
subset.nhoods <- str_detect(milo_res$annotation_indepth, "Cholangio")
reducedDim(liver_milo2, "UMAP")[colnames(chol_milo),] <- reducedDim(chol_milo, "UMAP")
chol_gr <-
plotNhoodGraphDA(
liver_milo2, milo_res,
subset.nhoods = subset.nhoods,
# ) =)[1:(length()-1)],
alpha = 0.1
) +
theme(legend.text = element_text(size=22), legend.title = element_text(size=24))
(chol_umap + chol_gr ) +
plot_layout(widths = c(1,2),
guides = "collect"
)

# fig4_bright1 +
# ggsave("~/milo_output/liver_endoGraph.pdf", width=9, height = 5)
Differential expression between DA neighbourhoods
We merge overlapping nhoods with significant DA and the same direction of logFC, and then test for differential expression between cells in disease-specific and healthy-specific nhoods. This allows us to perform a comparison without further clustering.
Here we find markers grouping gene expression counts by samples (i.e. we don’t treat cells as replicates, but exploit the replication structure used also for DA testing)
nhoodAdjacency found - using for nhood grouping
Nhoods aggregated into 2 groups
Table of significant DGE genes (FDR 10%)
marker.df[marker.df$adj.P.Val_1 < 0.1,]
Visualize as volcano
marker.df %>%
mutate(adj.P.Val_1 = ifelse(- log10(adj.P.Val_1) > 300, 1e-300, adj.P.Val_1)) %>%
mutate(label=ifelse(-log10(adj.P.Val_1) > 1.7, GeneID, NA)) %>%
ggplot(aes(logFC_2, -log10(adj.P.Val_1),
# color=highlight
)) +
geom_point() +
ggrepel::geom_text_repel(aes(label=label)) +
xlab("logFC") + ylab("- log10(Adj. P value)") +
theme_bw(base_size = 22)

NA
NA
Visualize as heatmap
(gene expression values are scaled between 0 and 1 for each gene)
marker_genes_up <- marker.df %>%
dplyr::filter(adj.P.Val_1 < 0.01 & logFC_2 > 2) %>%
pull(GeneID)
plotNhoodExpressionDA(liver_milo, milo_res, marker_genes_up, cluster_features = TRUE,
alpha = 0.1,
scale_to_1 = TRUE,
subset.nhoods = milo_res$annotation_lineage=="Cholangiocytes",
show_rownames = TRUE
) +
ylab("DE genes") +
theme(legend.text = element_text(size=22), legend.title = element_text(size=24)) +
plot_layout(heights = c(1,10))

NA
NA
GO term analysis
BiocManager::install('clusterProfiler')
Bioconductor version 3.10 (BiocManager 1.30.10), R 3.6.3 (2020-02-29)
Installing package(s) 'clusterProfiler'
trying URL 'https://bioconductor.org/packages/3.10/bioc/src/contrib/clusterProfiler_3.14.3.tar.gz'
Content type 'application/x-gzip' length 2634460 bytes (2.5 MB)
==================================================
downloaded 2.5 MB
* installing *source* package ‘clusterProfiler’ ...
** using staged installation
** R
** data
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
Execution halted
* removing ‘/home/jovyan/R/x86_64-pc-linux-gnu-library/3.6/clusterProfiler’
* restoring previous ‘/home/jovyan/R/x86_64-pc-linux-gnu-library/3.6/clusterProfiler’
em_res_up %>%
top_n(40, -log10(qvalue)) %>%
mutate(Term=factor(ID, levels=rev(unique(ID)))) %>%
ggplot(aes(Term, -log10(qvalue))) +
geom_point() +
coord_flip() +
xlab("GO Biological Function") + ylab("-log10(Adj. p-value)") +
theme_bw(base_size=14) +
ggtitle("Markers of healthy")

Full GO enrichment - up in cirrhotic
(geneID column indicates which genes belong to gene ontology)
em_res_up
Assemble figure
fig4_bottom <- ((fig4_bleft + plot_layout()) |
((fig4_bright1 + plot_layout(tag_level = 'keep')) / (fig4_bbright + plot_layout())) +
plot_layout(heights = c(1,1.6))
) +
plot_layout(widths=c(1,1.2))
(fig4_top / fig4_bottom) +
plot_layout(heights=c(1,1.8)) +
ggsave("~/milo_output/fig4.pdf", height = 26, width = 22, useDingbats=FALSE)
# ggsave("~/milo/ms/figures/figs/figure5.pdf", height = 26, width = 22, useDingbats=FALSE)
Assemble supplementary figure
p1 <- plot_grid(pval_hist,
volcano + ylab("- log10(Spatial FDR)"),
frac_hist, nrow=1,
labels = c("A", "B", "C"))
cowplot::plot_grid(p1, go_plot, rel_heights = c(1,1.5), ncol=1, labels = c("", "D")) +
ggsave("~/milo/ms/supplement/suppl_figs/suppl_fig6.pdf", height = 7, width=8)
ggsave("~/milo_output/liver_supplementary.png", height = 7, width=8)
LS0tCnRpdGxlOiAiTWlsbzogbGl2ZXIgY2lycmhvc2lzIGFuYWx5c2lzIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgojIyBJbnRyb2R1Y3Rpb24KCkluIHRoaXMgbm90ZWJvb2sgd2UgZGVtb25zdHJhdGUgaG93IHRvIHVzZSBNaWxvIHRvIGRldGVjdCBhYmhlcnJhbnQgY2VsbCBzdGF0ZXMgaW4gZGlzZWFzZWQgdGlzc3VlcywgdXNpbmcgYSBkYXRhc2V0IG9mIGhlcGF0aWMgbm9uLXBhcmVuY2h5bWFsIGNlbGxzIGlzb2xhdGVkIGZyb20gNSBoZWFsdGh5IGFuZCA1IGNpcnJob3RpYyBodW1hbiBsaXZlcnMuIFtSYW1hY2hhbmRyYW4gZXQgYWwuIDIwMTldKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNTg2LTAxOS0xNjMxLTMjU2VjMSkgKEdFTyBhY2Nlc3NpaW9uOiBHU0UxMzYxMDMpLgoKYGBge3J9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CiAgbGlicmFyeSh0aWR5dmVyc2UpCiAgbGlicmFyeShpcmxiYSkKICBsaWJyYXJ5KERyb3BsZXRVdGlscykKICBsaWJyYXJ5KHNjYXRlcikKICBsaWJyYXJ5KHNjcmFuKQogIGxpYnJhcnkoU2V1cmF0KSAjIyBqdXN0IDQgbG9hZGluZyB0aGUgb2JqZWN0CiAgbGlicmFyeShtaWxvUikKICBsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQogIGxpYnJhcnkocGF0Y2h3b3JrKQogIGxpYnJhcnkoaWdyYXBoKQogIGxpYnJhcnkoUkNvbG9yQnJld2VyKQogIGxpYnJhcnkoY293cGxvdCkKICB9KQpgYGAKCiMjIExvYWQgZGF0YQoKV2UgZG93bmxvYWRlZCB0aGUgZGF0YXNldCBhbmQgYW5ub3RhdGlvbnMgc3RvcmVkIGluIFNldXJhdCBvYmplY3QgZnJvbSBbaGVyZV0oaHR0cHM6Ly9kYXRhc2hhcmUuaXMuZWQuYWMudWsvaGFuZGxlLzEwMjgzLzM0MzMpLCBhcyBpbmRpY2F0ZWQgYnkgdGhlIGF1dGhvcnMuCgpgYGB7cn0KbG9hZCgiL25mcy90ZWFtMjA1L2VkNi9kYXRhL1JhbWFjaGFuZHJhbjIwMTlfbGl2ZXIvdGlzc3VlLnJkYXRhIikKCiMjIENvbnZlcnQgdG8gU2luZ2xlQ2VsbEV4cGVyaW1lbnQKbGl2ZXJfc2NlIDwtIFNpbmdsZUNlbGxFeHBlcmltZW50KGFzc2F5ID0gbGlzdChjb3VudHM9dGlzc3VlQHJhdy5kYXRhLCBsb2djb3VudHM9dGlzc3VlQGRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IHRpc3N1ZUBtZXRhLmRhdGEpCgpsaXZlcl9zY2UKYGBgCgojIyBQcmVwcm9jZXNzaW5nCgojIyMgRmVhdHVyZSBzZWxlY3Rpb24KCmBgYHtyfQpkZWNfbGl2ZXIgPC0gbW9kZWxHZW5lVmFyKGxpdmVyX3NjZSkKCmZpdF9saXZlciA8LSBtZXRhZGF0YShkZWNfbGl2ZXIpCnBsb3QoZml0X2xpdmVyJG1lYW4sIGZpdF9saXZlciR2YXIsIHhsYWI9Ik1lYW4gb2YgbG9nLWV4cHJlc3Npb24iLAogICAgeWxhYj0iVmFyaWFuY2Ugb2YgbG9nLWV4cHJlc3Npb24iKQoKaHZncyA8LSBnZXRUb3BIVkdzKGRlY19saXZlciwgbj0zMDAwKQpgYGAKCiMjIyBEaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gd2l0aCBQQ0EKCmBgYHtyLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTR9CmxpdmVyX3NjZSA8LSBydW5QQ0EobGl2ZXJfc2NlLCBzdWJzZXRfcm93PWh2Z3MsIG5jb21wb25lbnRzPTExKQoKcGxvdFBDQShsaXZlcl9zY2UsIGNvbG91cl9ieT0iY29uZGl0aW9uIiwgbmNvbXBvbmVudHM9MykKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0KbGl2ZXJfc2NlIDwtIHJ1blVNQVAobGl2ZXJfc2NlLCBkaW1yZWQ9IlBDQSIsIG5jb21wb25lbnRzPTIpCgpzY2F0ZXI6OnBsb3RVTUFQKGxpdmVyX3NjZSwgY29sb3VyX2J5PSJjb25kaXRpb24iLCBwb2ludF9hbHBoYT0xLCAgcG9pbnRfc2l6ZT0wLjUpCnNjYXRlcjo6cGxvdFVNQVAobGl2ZXJfc2NlLCBjb2xvdXJfYnk9ImRhdGFzZXQiLCBwb2ludF9hbHBoYT0wLjMsICBwb2ludF9zaXplPTAuNSkKc2NhdGVyOjpwbG90VU1BUChsaXZlcl9zY2UsIGNvbG91cl9ieT0iYW5ub3RhdGlvbl9saW5lYWdlIiwgcG9pbnRfYWxwaGE9MC4zLCAgcG9pbnRfc2l6ZT0wLjUsIHRleHRfYnk9J2Fubm90YXRpb25fbGluZWFnZScpCiMgc2NhdGVyOjpwbG90VU1BUChsaXZlcl9zY2UsIGNvbG91cl9ieT0nYW5ub3RhdGlvbl9pbmRlcHRoJywgcG9pbnRfYWxwaGE9MC4zLCAgcG9pbnRfc2l6ZT0wLjUsIHRleHRfYnk9J2Fubm90YXRpb25faW5kZXB0aCcpCmBgYAoKTm90YWJseSwgdGhpcyBkYXRhc2V0IGRvZXNuJ3QgYXBwZWFyIHRvIGRpc3BsYXkgYSBiYXRjaCBlZmZlY3QKCiMjIERBIGFuYWx5c2lzIHdpdGggTWlsbwoKV2UgdGVzdCBmb3IgZGlmZmVyZW50aWFsIGFidW5kYW5jZSBiZXR3ZWVuIGhlYWx0aHkgYW5kIGNpcnJob3RpYyBsaXZlcnMuIFdlIHN0YXJ0IGJ5IGRlZmluaW5nIG5laWdoYm91cmhvb2RzIHdpdGggcmVmaW5lZCBzYW1wbGluZyBvbiB0aGUgS05OIGdyYXBoLiBXZSBpbnNwZWN0IHRoZSBzaXplIG9mIG5laWdoYm91cmhvb2RzLgoKYGBge3J9CmxpdmVyX21pbG8gPC0gTWlsbyhsaXZlcl9zY2UpCgojIyBCdWlsZCBLTk4gZ3JhcGgKbGl2ZXJfbWlsbyA8LSBidWlsZEdyYXBoKGxpdmVyX21pbG8sIGQgPSAxMSwgaz0zMCkKCiMjIENvbXB1dGUgbmVpZ2hib3VyaG9vZHMgd2l0aCByZWZpbmVkIHNhbXBsaW5nCmxpdmVyX21pbG8gPC0gbWFrZU5ob29kcyhsaXZlcl9taWxvLCBrPTMwLCBkPTExLCBwcm9wID0gMC4wNSwgcmVmaW5lZD1UUlVFKQpwbG90Tmhvb2RTaXplSGlzdChsaXZlcl9taWxvLCBiaW5zPTE1MCkKYGBgCgpUaGVuIHdlIG1ha2UgYSBkZXNpZ24gbWF0cml4IGZvciB0aGUgZGlmZmVyZW50aWFsIHRlc3QsIGFzc2lnbmluZyBzYW1wbGVzIHRvIGNvbmRpdGlvbnMuCgpgYGB7cn0KbGl2ZXJfbWV0YSA8LSBhcy50aWJibGUoY29sRGF0YShsaXZlcl9taWxvKVssYygiZGF0YXNldCIsImNvbmRpdGlvbiIpXSkKbGl2ZXJfbWV0YSA8LSBkaXN0aW5jdChsaXZlcl9tZXRhKSAlPiUKICBtdXRhdGUoY29uZGl0aW9uPWZhY3Rvcihjb25kaXRpb24sIGxldmVscz1jKCJVbmluanVyZWQiLCAiQ2lycmhvdGljIikpKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoImRhdGFzZXQiKQpgYGAKCk5vdyB3ZSBjYW4gY291bnQgY2VsbHMgaW4gbmVpZ2hib3VyaG9vZHMgYW5kIHBlcmZvcm0gdGhlIERBIHRlc3QuCgpgYGB7cn0KbGl2ZXJfbWlsbyA8LSBjb3VudENlbGxzKGxpdmVyX21pbG8sIHNhbXBsZXMgPSAiZGF0YXNldCIsIG1ldGEuZGF0YSA9IGRhdGEuZnJhbWUoY29sRGF0YShsaXZlcl9taWxvKVssYygiZGF0YXNldCIsImNvbmRpdGlvbiIpXSkgKQoKbGl2ZXJfbWlsbyA8LSBjYWxjTmhvb2REaXN0YW5jZShsaXZlcl9taWxvLCBkPTExKQptaWxvX3JlcyA8LSB0ZXN0Tmhvb2RzKGxpdmVyX21pbG8sIGRlc2lnbiA9IH4gY29uZGl0aW9uLCBkZXNpZ24uZGYgPSBsaXZlcl9tZXRhLCBmZHIud2VpZ2h0aW5nID0gImstZGlzdGFuY2UiKQpgYGAKCiMjIEV4cGxvcmF0aW9uIG9mIERBIHJlc3VsdHMKCldlIGNhbiBzdGFydCBieSBsb29raW5nIGF0IHNvbWUgYmFzaWMgc3RhdHMKCmBgYHtyfQpwdmFsX2hpc3QgPC0gbWlsb19yZXMgJT4lCiAgZ2dwbG90KGFlcyhQVmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucz01MCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0xNCkKCnZvbGNhbm8gPC0KICBtaWxvX3JlcyAlPiUKICBnZ3Bsb3QoYWVzKGxvZ0ZDLCAtbG9nMTAoU3BhdGlhbEZEUikpKSArCiAgZ2VvbV9wb2ludChzaXplPTAuNCwgYWxwaGE9MC4yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMSkpICsKICB4bGFiKCJsb2ctRm9sZCBDaGFuZ2UiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplPTE0KQoKcHZhbF9oaXN0ICsgdm9sY2FubwpgYGAKClRoZSBkaXN0cmlidXRpb24gb2YgUC12YWx1ZXMgbG9va3Mgc2Vuc2libGUgYW5kIGZyb20gdGhlIHZvbGNhbm8gcGxvdCB3ZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSBpZGVudGlmaWVkIHNvbWUgREEgbmVpZ2hib3VyaG9vZHMgYXQgMTAlIEZEUi4KV2UgY2FuIHZpc3VhbGl6ZSBEQSBuZWlnaGJvdXJob29kcyBidWlsZGluZyBhbiBhYnN0cmFjdGVkIGdyYXBoCgpgYGB7ciwgZmlnLndpZHRoPTE0LCBmaWcuaGVpZ2h0PTEwfQpsaXZlcl9taWxvIDwtIGJ1aWxkTmhvb2RHcmFwaChsaXZlcl9taWxvKQpwbG90Tmhvb2RHcmFwaERBKGxpdmVyX21pbG8sIG1pbG9fcmVzLCBhbHBoYSA9IDAuMDUpCmBgYAoKYGBge3J9CiMjIFNhdmUgbWlsbyBvYmplY3QgYW5kIHJlc3VsdHMKIyBzYXZlUkRTKGxpdmVyX21pbG8sIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9SYW1hY2hhbmRyYW4yMDE5X2xpdmVyL3Rpc3N1ZV9taWxvLlJEUyIpCnNhdmVSRFMobGl2ZXJfbWlsbywifi9saXZlcl9taWxvXzIwMjAxMDA4LlJEUyIpCiMgd3JpdGVfY3N2KG1pbG9fcmVzLCAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL1JhbWFjaGFuZHJhbjIwMTlfbGl2ZXIvbWlsb19yZXN1bHRzLmNzdiIpCndyaXRlX2NzdihtaWxvX3JlcywiL25mcy90ZWFtMjA1L2VkNi9kYXRhL1JhbWFjaGFuZHJhbjIwMTlfbGl2ZXIvbGl2ZXJfcmVzdWx0c18yMDIwMTAwOC5jc3YiKQpgYGAKYGBge3IsIGVjaG89RkFMU0V9CmxpdmVyX21pbG8gPC0gcmVhZFJEUygifi9saXZlcl9taWxvXzIwMjAxMDA4LlJEUyIpCiMgbWlsb19yZXMgPC0gcmVhZF9jc3YoIn4vbGl2ZXJfcmVzdWx0c18yMDIwMTAwOC5jc3YiKQptaWxvX3JlcyA8LSByZWFkX2NzdigiL25mcy90ZWFtMjA1L2VkNi9kYXRhL1JhbWFjaGFuZHJhbjIwMTlfbGl2ZXIvbGl2ZXJfcmVzdWx0c18yMDIwMTAwOC5jc3YiKQpgYGAKCk1ha2luZyBmaWd1cmVzIGZvciB0aGUgbWFudXNjcmlwdAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xMH0KY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKGxpdmVyX21pbG8kYW5ub3RhdGlvbl9saW5lYWdlKSkKZ2V0UGFsZXR0ZSA9IGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCg5LCAiU2V0MiIpKQoKdW1hcF9kZiA8LSBkYXRhLmZyYW1lKHJlZHVjZWREaW0obGl2ZXJfbWlsbywgIlVNQVAiKSkKY29sbmFtZXModW1hcF9kZikgPC0gYygiVU1BUF8xIiwgIlVNQVBfMiIpCgp1bWFwMSA8LSBjYmluZCh1bWFwX2RmLCBhbm5vdGF0aW9uX2xpbmVhZ2U9bGl2ZXJfbWlsbyRhbm5vdGF0aW9uX2xpbmVhZ2UpICU+JQogIGdncGxvdChhZXMoVU1BUF8xLCBVTUFQXzIsIGNvbG9yPWFzLmNoYXJhY3Rlcihhbm5vdGF0aW9uX2xpbmVhZ2UpKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFscGhhPTAuNSkgKwogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gLiAlPiUKICAgICAgICAgICAgICBncm91cF9ieShhbm5vdGF0aW9uX2xpbmVhZ2UpICU+JQogICAgICAgICAgICAgIHN1bW1hcmlzZShVTUFQXzE9bWVhbihVTUFQXzEpLCBVTUFQXzI9bWVhbihVTUFQXzIpKSwKICAgICAgICAgICAgYWVzKGxhYmVsPWFubm90YXRpb25fbGluZWFnZSksIGNvbG9yPSJibGFjayIsIHNpemU9NgogICAgICAgICAgICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWdldFBhbGV0dGUoY29sb3VyQ291bnQpKSArCiAgZ3VpZGVzKGNvbG9yPSJub25lIikgKwogIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIyKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpKQoKdW1hcDIgPC0KICBjYmluZCh1bWFwX2RmLCBjb25kaXRpb249YXMuY2hhcmFjdGVyKGxpdmVyX21pbG8kY29uZGl0aW9uKSkgJT4lCiAgZ2dwbG90KGFlcyhVTUFQXzEsIFVNQVBfMiwgY29sb3I9Y29uZGl0aW9uKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIiwgbmFtZT0nJykgKwogIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICBjb29yZF9maXhlZCgpICsKICBndWlkZXMoY29sb3I9J25vbmUnKSArCiAgZmFjZXRfd3JhcChjb25kaXRpb25+LiwgbmNvbD0xKSArCiAgdGhlbWVfbm90aGluZyhmb250X3NpemUgPSAyMikgKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uPWMoMC45LDAuOSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvcj1OQSksIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0yMikpCgpuaF9ncmFwaF9wbCA8LSBwbG90Tmhvb2RHcmFwaERBKGxpdmVyX21pbG8sIG1pbG9fcmVzLCBhbHBoYSA9IDAuMSkgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjIpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0yNCkpICsKICBjb29yZF9maXhlZCgpCgpmaWc0X3RvcCA8LSAodW1hcDEgfCB1bWFwMiB8IG5oX2dyYXBoX3BsKSArCiAgcGxvdF9sYXlvdXQod2lkdGhzID0gYygzLDEsMykpCgpmaWc0X3RvcCArCiAgZ2dzYXZlKCJ+L21pbG9fb3V0cHV0L2xpdmVyX2VtYmVkZGluZy5wZGYiLCB3aWR0aD0xNSwgaGVpZ2h0ID0gMTApCmBgYAoKTmV4dCwgd2UgY2FuIGNoZWNrIHRoZSBjZWxsIHR5cGVzIHdoZXJlIHdlIG9ic2VydmUgbW9zdCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGhlYWx0aHkgYW5kIGNpcnJob3RpYyBjZWxscywgYnkgdGFraW5nIHRoZSBtb3N0IGZyZXF1ZW50IGNlbGwgdHlwZSBpbiBlYWNoIG5laWdoYm91cmhvb2QuCgpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MTB9CiMgQWRkIGFubm90YXRpb24gb2YgbW9zdCBmcmVxdWVudCBjZWxsIHR5cGUgcGVyIG5ob29kIHRvIG1pbG8gcmVzdWx0cyB0YWJsZQptaWxvX3JlcyA8LSBhbm5vdGF0ZU5ob29kcyhsaXZlcl9taWxvLCBtaWxvX3JlcywgImFubm90YXRpb25faW5kZXB0aCIpCmFubm9fZGYgPC0gZGF0YS5mcmFtZShsaXZlcl9taWxvQGNvbERhdGEpICU+JQogIGRpc3RpbmN0KGFubm90YXRpb25fbGluZWFnZSwgYW5ub3RhdGlvbl9pbmRlcHRoKQptaWxvX3JlcyA8LSBsZWZ0X2pvaW4obWlsb19yZXMsIGFubm9fZGYsIGJ5PSJhbm5vdGF0aW9uX2luZGVwdGgiKQpgYGAKCldlIGZpcnN0IGNoZWNrIHRoYXQgbmVpZ2hib3VyaG9vZHMgYXJlIHF1aXRlIGhvbW9nZW5lb3VzCgpgYGB7cn0KZnJhY19oaXN0IDwtIGdncGxvdChtaWxvX3JlcywgYWVzKGFubm90YXRpb25faW5kZXB0aF9mcmFjdGlvbikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zPTMwKSArCiAgeGxhYigiRnJhY3Rpb24gb2YgY2VsbHMgaW4gXG5tb3N0IGFidW5kYW50IGNsdXN0ZXIiKSArCiAgeWxhYigiIyBuZWlnaGJvdXJob29kcyIpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MTQpCgpmcmFjX2hpc3QKYGBgCgpJIGNhbiByZWNvdmVyIGFsbCB0aGUgY2x1c3RlcnMgd2hlcmUgREEgd2FzIGRldGVjdGVkIGluIHRoZSBvcmlnaW5hbCBwYXBlciAoc2VlIGFsbCB0aGUgYmFycGxvdHMgZm9yIGVhY2ggbGluZWFnZSkgYW5kIG1vcmUhIEFsbCBpbiBhIHNpbmdsZSBhbmFseXNpcywgYW5kIHdpdGhvdXQga25vd2luZyB3aGVyZSB0aGUgc3ViY2x1c3RlcnMgYXJlLiBMZXQncyBiZWFyIGluIG1pbmQgdGhhdCBwb3NpdGl2ZSBsb2dGQwoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0KZ3JvdXAuYnkgPSAiYW5ub3RhdGlvbl9pbmRlcHRoIgpwYXBlcl9EQSA8LSBsaXN0KGNpcnJob3RpYz1jKCJNUHMgKDQpIiwiTVBzICg1KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVuZG90aGVsaWEgKDYpIiwgIkVuZG90aGVsaWEgKDcpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWVzICgzKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRjZWxscyAoMikiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNeW9maWJyb2JsYXN0cyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgIGhlYWx0aHk9YygiTVBzICg3KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJFbmRvdGhlbGlhICgxKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJUY2VsbHMgKDEpIiwgIlRjZWxscyAoMykiLCJUY2VsbHMgKDEpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIklMQ3MgKDEpIgogICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgKQoKZXhwREFfZGYgPC0gYmluZF9yb3dzKAogIGRhdGEuZnJhbWUoYW5ub3RhdGlvbl9pbmRlcHRoID0gcGFwZXJfREFbWyJjaXJyaG90aWMiXV0sIHByZWRfREE9ImNpcnJob3RpYyIpLAogIGRhdGEuZnJhbWUoYW5ub3RhdGlvbl9pbmRlcHRoID0gcGFwZXJfREFbWyJoZWFsdGh5Il1dLCBwcmVkX0RBPSJoZWFsdGh5IikKICApCgpwbDEgPC0gbWlsb19yZXMgJT4lCiAgbGVmdF9qb2luKGV4cERBX2RmKSAlPiUKICBtdXRhdGUoaXNfc2lnbmlmID0gaWZlbHNlKFNwYXRpYWxGRFIgPCAwLjEsIDEsIDApKSAlPiUKICBtdXRhdGUobG9nRkNfY29sb3IgPSBpZmVsc2UoaXNfc2lnbmlmPT0xLCBsb2dGQywgTkEpKSAlPiUKICBhcnJhbmdlKGFubm90YXRpb25fbGluZWFnZSkgJT4lCiAgbXV0YXRlKE5ob29kPWZhY3RvcihOaG9vZCwgbGV2ZWxzPXVuaXF1ZShOaG9vZCkpKSAlPiUKICBnZ3Bsb3QoYWVzKGFubm90YXRpb25faW5kZXB0aCwgbG9nRkMsIGNvbG9yPWxvZ0ZDX2NvbG9yKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50MigpICsKICBndWlkZXMoY29sb3I9Im5vbmUiKSArCiAgeGxhYihncm91cC5ieSkgKyB5bGFiKCJMb2cgRm9sZCBDaGFuZ2UiKSArCiAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbShhbHBoYT0xKSArCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF9ncmlkKGFubm90YXRpb25fbGluZWFnZX4uLCBzY2FsZXM9ImZyZWUiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MjIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkgPSAgZWxlbWVudF90ZXh0KGFuZ2xlPTApLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICApCgpwbDIgPC0gbWlsb19yZXMgJT4lCiAgbGVmdF9qb2luKGV4cERBX2RmKSAlPiUKICAjIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKHByZWRfREEpKSAlPiUKICBncm91cF9ieShhbm5vdGF0aW9uX2luZGVwdGgpICU+JQogIHN1bW1hcmlzZShwcmVkX0RBPWRwbHlyOjpmaXJzdChwcmVkX0RBKSwgYW5ub3RhdGlvbl9saW5lYWdlPWRwbHlyOjpmaXJzdChhbm5vdGF0aW9uX2xpbmVhZ2UpKSAlPiUKICBtdXRhdGUoZW5kPWlmZWxzZShwcmVkX0RBPT0iaGVhbHRoeSIsIDAsIDEpLAogICAgICAgICBzdGFydD1pZmVsc2UocHJlZF9EQT09ImhlYWx0aHkiLCAxLCAwKSkgJT4lCiAgZ2dwbG90KGFlcyhhbm5vdGF0aW9uX2luZGVwdGgsIHN0YXJ0LCB4ZW5kID0gYW5ub3RhdGlvbl9pbmRlcHRoLCB5ZW5kID0gZW5kLCBjb2xvcj1wcmVkX0RBKSkgKwogIGdlb21fc2VnbWVudChzaXplPTEsYXJyb3c9YXJyb3cobGVuZ3RoID0gdW5pdCgwLjEsICJucGMiKSwgdHlwZT0iY2xvc2VkIikpICsKICBjb29yZF9mbGlwKCkgKwogIHhsYWIoImFubm90YXRpb24iKSArCiAgZmFjZXRfZ3JpZChhbm5vdGF0aW9uX2xpbmVhZ2V+LiwKICAgICMgYW5ub3RhdGlvbl9saW5lYWdlfiJSYW1hY2hhbmRyYW4gZXQgYWwuXG5EQSBwcmVkaWN0aW9ucyIsCiAgICAgICAgICAgICBzY2FsZXM9ImZyZWUiLCBzcGFjZT0iZnJlZSIpICsKICAjIGd1aWRlcyhjb2xvcj0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIsIGRpcmVjdGlvbiA9IC0xLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiZW5yaWNoZWQgaW4gY2lycmhvdGljIiwgImVucmljaGVkIGluIGhlYWx0aHkiKSwKICAgICAgICAgICAgICAgICAgICAgbmEudHJhbnNsYXRlID0gRiwKICAgICAgICAgICAgICAgICAgICAgbmFtZT0iUmFtYWNoYW5kcmFuIGV0IGFsLlxuREEgcHJlZGljdGlvbnMiKSArCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChuY29sID0gMSkpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MjIpICsKICB5bGltKC0wLjEsMS4xKSArCiAgdGhlbWUoc3RyaXAudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwwLDAsMCksICJjbSIpLCBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCmZpZzRfYmxlZnQgPC0gKHBsMiArIHBsMSArCiAgcGxvdF9sYXlvdXQod2lkdGhzPWMoMSwxMCksIGd1aWRlcyA9ICJjb2xsZWN0IikgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAndG9wJywgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAwKSkKCmZpZzRfYmxlZnQgKwogIGdnc2F2ZSgifi9taWxvX291dHB1dC9saXZlcl9EQWNvbXBhcmlzb24ucGRmIiwgd2lkdGg9OCwgaGVpZ2h0ID0gMTMpCmBgYAoKIyMgQ2xvc2UtdXAgb24gRW5kb3RoZWxpYWwgbGluZWFnZQoKYGBge3J9CmVuZG9fbWlsbyA8LSBzY2F0ZXI6OnJ1blVNQVAobGl2ZXJfbWlsb1ssbGl2ZXJfbWlsbyRhbm5vdGF0aW9uX2xpbmVhZ2U9PSJFbmRvdGhlbGlhIl0sICBkaW1yZWQ9J1BDQScpCnBsb3RVTUFQKGVuZG9fbWlsbywgY29sb3VyX2J5ID0gImFubm90YXRpb25faW5kZXB0aCIpCmBgYAoKRmlsdGVyIG91dCBjZWxscyB0aGF0IHNob3cgY29udGFtaW5hdGlvbiBmcm9tIGltbXVuZSBjZWxscyAoZXhwcmVzc2lvbiBvZiBpbW11bmUgbWFya2VycykKCmBgYHtyfQprZWVwIDwtIGxvZ2NvdW50cyhlbmRvX21pbG8pWyJDRDE5IixdID09IDAgfCBsb2djb3VudHMoZW5kb19taWxvKVsiTVM0QTEiLF0gPT0gMAplbmRvX21pbG8gPC0gZW5kb19taWxvWyxrZWVwXQplbmRvX21pbG8gPC0gc2NhdGVyOjpydW5VTUFQKGVuZG9fbWlsbywgIGRpbXJlZD0nUENBJykKCnBsb3RVTUFQKGVuZG9fbWlsbywgY29sb3VyX2J5ID0gImFubm90YXRpb25faW5kZXB0aCIpCmBgYAoKYGBge3J9CnVtYXBfZGYgPC0gZGF0YS5mcmFtZShyZWR1Y2VkRGltKGVuZG9fbWlsbywgIlVNQVAiKSkKY29sbmFtZXModW1hcF9kZikgPC0gYygiVU1BUF8xIiwgIlVNQVBfMiIpCgplbmRvX3VtYXAgPC0gY2JpbmQodW1hcF9kZiwgY29uZGl0aW9uPWVuZG9fbWlsbyRjb25kaXRpb24pICU+JQogICBnZ3Bsb3QoYWVzKFVNQVBfMSwgVU1BUF8yLCBjb2xvcj1jb25kaXRpb24pKSArCiAgZ2VvbV9wb2ludChzaXplPTAuMywgYWxwaGE9MC41KSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiLCBuYW1lPScnKSArCiAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIGd1aWRlcyhjb2xvcj0ibm9uZSIpICsKICBmYWNldF93cmFwKGNvbmRpdGlvbn4uLCBuY29sPTEpICsKICB0aGVtZV9ub3RoaW5nKCkgKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uPWMoMC45LDAuOSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvcj1OQSksIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0yMikpCmBgYAoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpdmVyX21pbG8yIDwtIGxpdmVyX21pbG8Kc3Vic2V0Lm5ob29kcyA8LSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkVuZG8iKQpyZWR1Y2VkRGltKGxpdmVyX21pbG8yLCAiVU1BUCIpW2NvbG5hbWVzKGVuZG9fbWlsbyksXSA8LSByZWR1Y2VkRGltKGVuZG9fbWlsbywgIlVNQVAiKSAKCgplbmRvX2dyIDwtCiAgcGxvdE5ob29kR3JhcGhEQSgKICBsaXZlcl9taWxvMiwgbWlsb19yZXMsCiAgc3Vic2V0Lm5ob29kcyA9IHN1YnNldC5uaG9vZHMsIAogICMgKSA9KVsxOihsZW5ndGgoKS0xKV0sIAogIGFscGhhID0gMC4xCiAgKSAgKwogICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTIyKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjQpKQogIApmaWc0X2JyaWdodDEgPC0gKChlbmRvX3VtYXAgKyBlbmRvX2dyICkgKyAKICBwbG90X2xheW91dCh3aWR0aHMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgZ3VpZGVzID0gImNvbGxlY3QiCiAgICAgICAgICAgICAgICApKSAKZmlnNF9icmlnaHQxICsKICBnZ3NhdmUoIn4vbWlsb19vdXRwdXQvbGl2ZXJfZW5kb0dyYXBoLnBkZiIsIHdpZHRoPTksIGhlaWdodCA9IDUpICAKYGBgCgoKIyMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGJldHdlZW4gREEgbmVpZ2hib3VyaG9vZHMKCldlIG1lcmdlIG92ZXJsYXBwaW5nIG5ob29kcyB3aXRoIHNpZ25pZmljYW50IERBIGFuZCB0aGUgc2FtZSBkaXJlY3Rpb24gb2YgbG9nRkMsIGFuZCB0aGVuIHRlc3QgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGJldHdlZW4gY2VsbHMgaW4gZGlzZWFzZS1zcGVjaWZpYyBhbmQgaGVhbHRoeS1zcGVjaWZpYyBuaG9vZHMuIFRoaXMgYWxsb3dzIHVzIHRvIHBlcmZvcm0gYSBjb21wYXJpc29uIHdpdGhvdXQgZnVydGhlciBjbHVzdGVyaW5nLgoKSGVyZSB3ZSBmaW5kIG1hcmtlcnMgZ3JvdXBpbmcgZ2VuZSBleHByZXNzaW9uIGNvdW50cyBieSBzYW1wbGUgKGkuZS4gd2UgZG9uJ3QgdHJlYXQgY2VsbHMgYXMgcmVwbGljYXRlcywgYnV0IGV4cGxvaXQgdGhlIHJlcGxpY2F0aW9uIHN0cnVjdHVyZSB1c2VkIGFsc28gZm9yIERBIHRlc3RpbmcpCmBgYHtyfQpsaWJyYXJ5KGxpbW1hKQpsaWJyYXJ5KGVkZ2VSKQoKbmhzIDwtIG5ob29kcyh4KQpuaG9vZC5hZGogPC0gbmhvb2RBZGphY2VuY3koeCkKZGEucmVzIDwtIG1pbG9fcmVzCgppcy5kYQojJyBAaW1wb3J0RnJvbSBpZ3JhcGggZ3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4IGNvbXBvbmVudHMKLmdyb3VwX25ob29kc19mcm9tX2FkamFjZW5jeSA8LSBmdW5jdGlvbihuaHMsIG5ob29kLmFkaiwgZGEucmVzLCBpcy5kYSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxmYy50aHJlc2hvbGQ9TlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybGFwPTEsIHN1YnNldC5uaG9vZHM9TlVMTCl7CgogICAgaWYoaXMubnVsbChuYW1lcyhuaHMpKSl7CiAgICAgICAgd2FybmluZygiTm8gbmFtZXMgYXR0cmlidXRlZCB0byBuaG9vZHMuIENvbnZlcnRpbmcgaW5kaWNlcyB0byBuYW1lcyIpCiAgICAgICAgbmFtZXMobmhzKSA8LSBhcy5jaGFyYWN0ZXIoYygxOmxlbmd0aChuaHMpKSkKICAgIH0KCiAgICAjIGFzc3VtZSBvcmRlciBvZiBuaHMgaXMgdGhlIHNhbWUgYXMgbmhvb2QuYWRqCiAgICBpZighaXMubnVsbChzdWJzZXQubmhvb2RzKSl7CiAgICAgICAgaWYobW9kZShzdWJzZXQubmhvb2RzKSAlaW4lIGMoImNoYXJhY3RlciIsICJsb2dpY2FsIiwgIm51bWVyaWMiKSl7CiAgICAgICAgICAgICMgZm9yY2UgdXNlIG9mIGxvZ2ljYWxzIGZvciBjb25zaXN0ZW5jeQogICAgICAgICAgICBpZihtb2RlKHN1YnNldC5uaG9vZHMpICVpbiUgYygiY2hhcmFjdGVyIiwgIm51bWVyaWMiKSl7CiAgICAgICAgICAgICAgICBzdWIubG9nIDwtIG5hbWVzKG5ocykgJWluJSBzdWJzZXQubmhvb2RzCiAgICAgICAgICAgIH0gZWxzZXsKICAgICAgICAgICAgICAgIHN1Yi5sb2cgPC0gc3Vic2V0Lm5ob29kcwogICAgICAgICAgICB9CgogICAgICAgICAgICBuaG9vZC5hZGogPC0gbmhvb2QuYWRqW3N1Yi5sb2csIHN1Yi5sb2ddCgogICAgICAgICAgICBpZihsZW5ndGgoaXMuZGEpID09IGxlbmd0aChuaHMpKXsKICAgICAgICAgICAgICAgIG5ocyA8LSBuaHNbc3ViLmxvZ10KICAgICAgICAgICAgICAgIGlzLmRhIDwtIGlzLmRhW3N1Yi5sb2ddCiAgICAgICAgICAgICAgICBkYS5yZXMgPC0gZGEucmVzW3N1Yi5sb2csIF0KICAgICAgICAgICAgfSBlbHNlewogICAgICAgICAgICAgICAgc3RvcCgiU3Vic2V0dGluZyBgaXMuZGFgIHZlY3RvciBsZW5ndGggZG9lcyBub3QgZXF1YWwgbmhvb2RzIGxlbmd0aCIpCiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2V7CiAgICAgICAgICAgIHN0b3AocGFzdGUwKCJJbmNvcnJlY3Qgc3Vic2V0dGluZyB2ZWN0b3IgcHJvdmlkZWQ6IiwgY2xhc3Moc3Vic2V0Lm5ob29kcykpKQogICAgICAgIH0KICAgIH0gZWxzZXsKICAgICAgICBpZihsZW5ndGgoaXMuZGEpICE9IG5jb2wobmhvb2QuYWRqKSl7CiAgICAgICAgICAgIHN0b3AoIlN1YnNldHRpbmcgYGlzLmRhYCB2ZWN0b3IgbGVuZ3RoIGlzIG5vdCB0aGUgc2FtZSBkaW1lbnNpb24gYXMgYWRqYWNlbmN5IikKICAgICAgICB9CiAgICB9CgogICAgIyMgY2hlY2sgZm9yIGNvbmNvcmRhbnQgc2lnbnMgLSBhc3N1bWUgb3JkZXIgaXMgdGhlIHNhbWUgYXMgbmhvb2RzCiAgICBpZihpc0ZBTFNFKG1lcmdlLmRpc2NvcmQpKXsKICAgICAgICBub256Lm5ocyA8LSBjb2xTdW1zKG5ob29kLmFkaikgPiAwCiAgICAgICAgbGxfbmFtZXMgPC0gZXhwYW5kLmdyaWQoYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSksIGMoMTpsZW5ndGgobmhzW25vbnoubmhzXSkpKQoKICAgICAgICBjb25jb3JkLnNpZ24gPC0gc2FwcGx5KDE6bnJvdyhsbF9uYW1lcyksIGZ1bmN0aW9uKHgpIHNpZ24oZGEucmVzW25vbnoubmhzLCBdW2FzLm51bWVyaWMobGxfbmFtZXNbeCwgMV0pLCBdJGxvZ0ZDKSA9PQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24oZGEucmVzW25vbnoubmhzLF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAyXSksIF0kbG9nRkMpKQogICAgICAgIHBhaXJzX2ludCA8LSBzYXBwbHkod2hpY2goY29uY29yZC5zaWduKSwgZnVuY3Rpb24oeCkgbGVuZ3RoKGludGVyc2VjdChuaHNbbm9uei5uaHNdW1tsbF9uYW1lc1t4LCAxXV1dLCBuaHNbbm9uei5uaHNdW1tsbF9uYW1lc1t4LCAyXV1dKSkpCiAgICAgICAgbGludGVyc2VjdCA8LSByZXAoMCwgbnJvdyhsbF9uYW1lcykpCiAgICAgICAgbGludGVyc2VjdFtjb25jb3JkLnNpZ25dIDwtIHBhaXJzX2ludAoKICAgICAgICAjIyBDb3VudCBhcyBjb25uZWN0ZWQgb25seSBuaG9vZHMgd2l0aCBhdCBsZWFzdCBuIHNoYXJlZCBjZWxscwogICAgICAgIGxpbnRlcnNlY3RfZmlsdCA8LSBpZmVsc2UoIWNvbmNvcmQuc2lnbiwgMCwgbGludGVyc2VjdCkKICAgICAgICBsbF9uYW1lcyA8LSBjYmluZChsbF9uYW1lcywgbGludGVyc2VjdF9maWx0KQoKICAgICAgICBuaG9vZC5hZGpbbm9uei5uaHMsIG5vbnoubmhzXSA8LSBsbF9uYW1lc1ssIDNdCiAgICB9CgogICAgaWYob3ZlcmxhcCA+IDEpewogICAgICAgICMgbG9vcCBvdmVyIGFkaiBkaW1lbnNpb25zIGFuZCBtYXNrIG91dCBjZWxscyB3aXRoIGluc3VmZmljaWVudCBvdmVybGFwcGluZyBjZWxscwogICAgICAgIG5vbnoubmhzIDwtIGNvbFN1bXMobmhvb2QuYWRqKSA+IDAKICAgICAgICBsbF9uYW1lcyA8LSBleHBhbmQuZ3JpZChjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSwgYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSkpCgogICAgICAgIGtlZXBfcGFpcnMgPC0gc2FwcGx5KDE6bnJvdyhsbF9uYW1lcykgLCBmdW5jdGlvbih4KSBhbnkobmhzW25vbnoubmhzXVtbbGxfbmFtZXNbeCwgMV1dXSAlaW4lIG5oc1tub256Lm5oc11bW2xsX25hbWVzW3gsIDJdXV0pKQogICAgICAgIHBhaXJzX2ludCA8LSBzYXBwbHkod2hpY2goa2VlcF9wYWlycyksIGZ1bmN0aW9uKHgpIGxlbmd0aChpbnRlcnNlY3QobmhzW25vbnoubmhzXVtbbGxfbmFtZXNbeCwgMV1dXSwgbmhzW25vbnoubmhzXVtbbGxfbmFtZXNbeCwgMl1dXSkpKQogICAgICAgIGxpbnRlcnNlY3QgPC0gcmVwKDAsIG5yb3cobGxfbmFtZXMpKQogICAgICAgIGxpbnRlcnNlY3Rba2VlcF9wYWlyc10gPC0gcGFpcnNfaW50CgogICAgICAgICMjIENvdW50IGFzIGNvbm5lY3RlZCBvbmx5IG5ob29kcyB3aXRoIGF0IGxlYXN0IG4gc2hhcmVkIGNlbGxzCiAgICAgICAgbGludGVyc2VjdF9maWx0IDwtIGlmZWxzZShsaW50ZXJzZWN0IDwgb3ZlcmxhcCwgMCwgbGludGVyc2VjdCkKICAgICAgICBsbF9uYW1lcyA8LSBjYmluZChsbF9uYW1lcywgbGludGVyc2VjdF9maWx0KQoKICAgICAgICBuaG9vZC5hZGpbbm9uei5uaHMsIG5vbnoubmhzXSA8LSBsbF9uYW1lc1ssIDNdCiAgICB9CgogICAgaWYoIWlzLm51bGwobGZjLnRocmVzaG9sZCkpewogICAgICAgIG5vbnoubmhzIDwtIGNvbFN1bXMobmhvb2QuYWRqKSA+IDAKICAgICAgICBsbF9uYW1lcyA8LSBleHBhbmQuZ3JpZChjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSwgYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSkpCgogICAgICAgICMgc2V0IGFkamFjZW5jeSB0byAwIGZvciBuaG9vZHMgd2l0aCBsZmMgPCB0aHJlc2hvbGQKICAgICAgICBsZmMucGFzcyA8LSBzYXBwbHkoMTpucm93KGxsX25hbWVzKSwgZnVuY3Rpb24oeCkgKGFicyhkYS5yZXNbbm9uei5uaHMsIF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAxXSksIF0kbG9nRkMpID49IGxmYy50aHJlc2hvbGQpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhYnMoZGEucmVzW25vbnoubmhzLCBdW2FzLm51bWVyaWMobGxfbmFtZXNbeCwgMl0pLCBdJGxvZ0ZDKSA+PSBsZmMudGhyZXNob2xkKSkKICAgICAgICBwYWlyc19pbnQgPC0gc2FwcGx5KHdoaWNoKGxmYy5wYXNzKSwgZnVuY3Rpb24oeCkgbGVuZ3RoKGludGVyc2VjdChuaHNbbm9uei5uaHNdW1tsbF9uYW1lc1t4LCAxXV1dLCBuaHNbbm9uei5uaHNdW1tsbF9uYW1lc1t4LCAyXV1dKSkpCiAgICAgICAgbGludGVyc2VjdFtsZmMucGFzc10gPC0gcGFpcnNfaW50CgogICAgICAgICMjIENvdW50IGFzIGNvbm5lY3RlZCBvbmx5IG5ob29kcyB3aXRoIGF0IGxlYXN0IG4gc2hhcmVkIGNlbGxzCiAgICAgICAgbGludGVyc2VjdF9maWx0IDwtIGlmZWxzZSghbGZjLnBhc3MsIDAsIGxpbnRlcnNlY3QpCiAgICAgICAgbGxfbmFtZXMgPC0gY2JpbmQobGxfbmFtZXMsIGxpbnRlcnNlY3RfZmlsdCkKCiAgICAgICAgbmhvb2QuYWRqW25vbnoubmhzLCBub256Lm5oc10gPC0gbGxfbmFtZXNbLCAzXQogICAgfQoKICAgICMgYmluYXJpc2UKICAgIG5ob29kLmFkaiA8LSBhcy5tYXRyaXgoKG5ob29kLmFkaiA+IDApICsgMCkKCiAgICBuLmRpbSA8LSBuY29sKG5ob29kLmFkaikKICAgIGlmKCFpc1N5bW1ldHJpYyhuaG9vZC5hZGopKXsKICAgICAgICBzdG9wKCJPdmVybGFwIG1hdHJpeCBpcyBub3Qgc3ltbWV0cmljIikKICAgIH0KCiAgICBpZihucm93KG5ob29kLmFkaikgIT0gbmNvbChuaG9vZC5hZGopKXsKICAgICAgICBzdG9wKCJOb24tc3F1YXJlIGRpc3RhbmNlIG1hdHJpeCAtIGNoZWNrIG5ob29kIHN1YnNldHRpbmciKQogICAgfQoKICAgIGcgPC0gZ3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KG5ob29kLmFkaiwgbW9kZT0idW5kaXJlY3RlZCIsIGRpYWc9RkFMU0UpCiAgICBncm91cHMgPC0gY29tcG9uZW50cyhnKSRtZW1iZXJzaGlwCgogICAgIyBvbmx5IGtlZXAgdGhlIGdyb3VwcyB0aGF0IGNvbnRhaW4gPj0gMSBEQSBuZWlnaGJvdXJob29kcwogICAga2VlcC5ncm91cHMgPC0gaW50ZXJzZWN0KHVuaXF1ZShncm91cHNbaXMuZGFdKSwgdW5pcXVlKGdyb3VwcykpCgogICAgcmV0dXJuKGdyb3Vwc1tncm91cHMgJWluJSBrZWVwLmdyb3Vwc10pCn0KCgogLnBlcmZvcm1fY291bnRzX2RnZSA8LSBmdW5jdGlvbihleHBycy5kYXRhLCB0ZXN0Lm1vZGVsLCBnZW5lLm9mZnNldD1nZW5lLm9mZnNldCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWwuY29udHJhc3RzPU5VTEwsIG4uY29lZj1OVUxMKXsKCiAgICAgaS5kZ2UgPC0gREdFTGlzdChjb3VudHM9ZXhwcnMuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgIGxpYi5zaXplPWxvZyhjb2xTdW1zKGV4cHJzLmRhdGEpKSkKCiAgICAgaWYoaXNUUlVFKGdlbmUub2Zmc2V0KSl7CiAgICAgICAgIG4uZ2VuZSA8LSBhcHBseShleHBycy5kYXRhLCAyLCBmdW5jdGlvbihYKSBzdW0oWCA+IDApKQogICAgICAgICB0ZXN0Lm1vZGVsIDwtIGNiaW5kKHRlc3QubW9kZWxbLCAxXSwgbi5nZW5lLCB0ZXN0Lm1vZGVsWywgYygyOm5jb2wodGVzdC5tb2RlbCkpXSkKICAgICAgICAgY29sbmFtZXModGVzdC5tb2RlbCkgPC0gYyhjb2xuYW1lcyh0ZXN0Lm1vZGVsKVsxXSwgIk5HZW5lcyIsIGNvbG5hbWVzKHRlc3QubW9kZWxbLCBjKDI6bmNvbCh0ZXN0Lm1vZGVsKSldKSkKICAgICB9CgogICAgIGkuZGdlIDwtIGVzdGltYXRlRGlzcChpLmRnZSwgdGVzdC5tb2RlbCkKICAgICBpLmZpdCA8LSBnbG1RTEZpdChpLmRnZSwgdGVzdC5tb2RlbCwgcm9idXN0PVRSVUUpCgogICAgIGlmKCFpcy5udWxsKG1vZGVsLmNvbnRyYXN0cykpewogICAgICAgICBtb2QuY29uc3RyYXN0IDwtIG1ha2VDb250cmFzdHMoY29udHJhc3RzPW1vZGVsLmNvbnRyYXN0cywgbGV2ZWxzPXRlc3QubW9kZWwpCiAgICAgICAgIGkucmVzIDwtIGFzLmRhdGEuZnJhbWUodG9wVGFncyhnbG1RTEZUZXN0KGkuZml0LCBjb250cmFzdD1tb2QuY29uc3RyYXN0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnQuYnk9J25vbmUnLCBuPUluZikpCiAgICAgfSBlbHNlewogICAgICAgICBpZihpcy5udWxsKG4uY29lZikpewogICAgICAgICAgICAgbi5jb2VmIDwtIG5jb2wodGVzdC5tb2RlbCkKICAgICAgICAgfQogICAgICAgICBpLnJlcyA8LSBhcy5kYXRhLmZyYW1lKHRvcFRhZ3MoZ2xtUUxGVGVzdChpLmZpdCwgY29lZj1uLmNvZWYpLCBzb3J0LmJ5PSdub25lJywgbj1JbmYpKQogICAgIH0KICAgICByZXR1cm4oaS5yZXMpCiB9CgpjZWxsMm5ob29kcyA8LSBmdW5jdGlvbih4KXsKICBuaHMgPC0gbGFwcGx5KG5ob29kcyh4KSwgZnVuY3Rpb24obmgpIGFzLnZlY3RvcihuaCkpCiAgIyBuaG9vZF9tYXQgPC0gbWF0cml4KG5yb3cgPSBuY29sKHgpLCBuY29sPWxlbmd0aChuaG9vZHMoeCkpKQogIG5ob29kX21hdCA8LSBzYXBwbHkobmhzLCBmdW5jdGlvbihuaCkgaWZlbHNlKDE6bmNvbCh4KSAlaW4lIG5oLCAxLCAwKSkKICByZXR1cm4obmhvb2RfbWF0KQp9Cgp4ID0gbGl2ZXJfbWlsbwpkYS5yZXMgPSBtaWxvX3JlcwpkYS5mZHI9MC4wNQphc3NheT0iY291bnRzIgpvdmVybGFwPTEKbGZjLnRocmVzaG9sZCA9IDEKbWVyZ2UuZGlzY29yZD1GQUxTRQpzdWJzZXQucm93ID0gaHZncwpnZW5lLm9mZnNldD1GQUxTRQpyZXR1cm4uZ3JvdXBzPUZBTFNFCnN1YnNldC5uaG9vZHMgPSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkVuZG8iKQpuYS5mdW5jdGlvbj0ibmEucGFzcyIKY29tcHV0ZS5uZXc9RkFMU0UKYml0cz1GQUxTRQoKYzJuIDwtIGNlbGwybmhvb2RzKHgpCgojIG5ob29kLmFkajEgPC0gdChjMm4pICUqJSBjMm4gCiMgbmhvb2QuYWRqMSA8LSBhcyhuaG9vZC5hZGoxLCAiZGdDTWF0cml4IikKIyAKIyAjIG5ob29kLmFkai5vbGQgPC0gbmhvb2RBZGphY2VuY3kobGl2ZXJfbWlsbykKIyBuaG9vZEFkamFjZW5jeShsaXZlcl9taWxvKSA8LSBhcy5tYXRyaXgobmhvb2QuYWRqMSkKIyAKIyBwaGVhdG1hcDo6cGhlYXRtYXAobmhvb2QuYWRqLm9sZFtyb3duYW1lcyhuaG9vZC5hZGoxKSwgcm93bmFtZXMobmhvb2QuYWRqMSldIC0gbmhvb2QuYWRqMSkKCiMgIyMgTWFrZSBncm91cHMKIyBjMm4gPC0gYzJuWyxzdWJzZXQubmhvb2RzICYgaXMuZGFdCiMgZGEucmVzIDwtIGRhLnJlc1tzdWJzZXQubmhvb2RzICYgaXMuZGEsXQpuZWdfbG9nZmMgPC0gZGEucmVzJGxvZ0ZDIDwgLSBsZmMudGhyZXNob2xkCnBvc19sb2dmYyA8LSBkYS5yZXMkbG9nRkMgPiBsZmMudGhyZXNob2xkCgpncjEgPC0gcm93U3VtcyhjMm5bLHN1YnNldC5uaG9vZHMgJiBpcy5kYSAmIG5lZ19sb2dmY10pID4gMApncjIgPC0gcm93U3VtcyhjMm5bLHN1YnNldC5uaG9vZHMgJiBpcy5kYSAmIHBvc19sb2dmY10pID4gMAoKIyBsZW5ndGgoKHN1YnNldC5uaG9vZHMpICYgKGlzLmRhKSAmIChuZWdfbG9nZmMpKQojIGcgPC0gZ3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KG5ob29kLmFkaiwgbW9kZT0idW5kaXJlY3RlZCIsIGRpYWc9RkFMU0UpCiMgICAgIGdyb3VwcyA8LSBjb21wb25lbnRzKGcpJG1lbWJlcnNoaXAKCgpmYWtlLm1ldGEgPC0gZGF0YS5mcmFtZSgiQ2VsbElEIj1jb2xuYW1lcyh4KSwgIk5ob29kLkdyb3VwIj1yZXAoTkEsIG5jb2woeCkpKQpyb3duYW1lcyhmYWtlLm1ldGEpIDwtIGZha2UubWV0YSRDZWxsSUQKZmFrZS5tZXRhWyJOaG9vZC5Hcm91cCJdIDwtIGlmZWxzZShncjEgJiAhZ3IyLCAxLCBpZmVsc2UoZ3IyICYgIWdyMSwgMiwgTkEpKQoKdW1hcF9kZlsnZ3InXSA8LSBmYWtlLm1ldGFbcm93bmFtZXModW1hcF9kZiksIk5ob29kLkdyb3VwIl0KZ2dwbG90KHVtYXBfZGYsIGFlcyhVTUFQXzEsIFVNQVBfMikpICsgZ2VvbV9wb2ludChhZXMoY29sb3I9Z3IpKQpgYGAKCgpgYGB7cn0KIyBmb3IoaSBpbiBzZXFfYWxvbmcobmhvb2QuZ3IpKXsKIyAgICAgbmhvb2QueCA8LSBuaHMuZGEuZ3IgPT0gbmhvb2QuZ3JbaV0KIyAgICAgIyBnZXQgdGhlIG5ob29kcwojICAgICBuaHMgPC0gbmhvb2RzKHgpCiMgICAgIGlmKCFpcy5udWxsKHN1YnNldC5uaG9vZHMpKXsKIyAgICAgICAgIG5ocyA8LSBuaHNbc3Vic2V0Lm5ob29kc10KIyAgICAgfQojIAojICAgICBpZighYW55KGlzLm5hKGZha2UubWV0YVt1bmxpc3QobmhzW25ob29kLnhdKSxdJE5ob29kLkdyb3VwKSkpewojICAgICAgICAgZmFrZS5tZXRhW3VubGlzdChuaHNbbmhvb2QueF0pLF0kTmhvb2QuR3JvdXBbIWlzLm5hKGZha2UubWV0YVt1bmxpc3QobmhzW25ob29kLnhdKSxdJE5ob29kLkdyb3VwKV0gPC0gTkEKIyAgICAgICAgIH0gZWxzZXsKIyAgICAgICAgICAgICBmYWtlLm1ldGFbdW5saXN0KG5oc1tuaG9vZC54XSksXSROaG9vZC5Hcm91cCA8LSBuaG9vZC5ncltpXQojICAgICAgICAgfQojIH0KIyBvbmx5IGNvbXBhcmUgYWdhaW5zdCB0aGUgb3RoZXIgREEgbmVpZ2hib3VyaG9vZHMKeCA8LSB4WywgIWlzLm5hKGZha2UubWV0YSROaG9vZC5Hcm91cCldCmZha2UubWV0YSA8LSBmYWtlLm1ldGFbIWlzLm5hKGZha2UubWV0YSROaG9vZC5Hcm91cCksIF0KCmlmKCFpcy5udWxsKHN1YnNldC5yb3cpKXsKICAgIHggPC0geFtzdWJzZXQucm93LCAsIGRyb3A9RkFMU0VdCn0KCmZha2UubWV0YVssInNhbXBsZV9pZCJdIDwtIHNhcHBseShzdHJzcGxpdChmYWtlLm1ldGEkQ2VsbElELCAiXyIpLCBmdW5jdGlvbih4KSBwYXN0ZSh4WzFdLCB4WzJdLCBzZXA9Il8iKSkKZmFrZS5tZXRhWywnc2FtcGxlX2dyb3VwJ10gPC0gcGFzdGUoZmFrZS5tZXRhWywic2FtcGxlX2lkIl0sIGZha2UubWV0YVssIk5ob29kLkdyb3VwIl0sIHNlcD0iXyIpCgoKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KIyAKIyAKIyBpZihpcy5udWxsKG5hLmZ1bmN0aW9uKSl7CiMgICAgIHdhcm5pbmcoIk5VTEwgcGFzc2VkIHRvIG5hLmZ1bmN0aW9uLCB1c2luZyBuYS5wYXNzIikKIyAgICAgbmEuZnVuYyA8LSBnZXQoIm5hLnBhc3MiKQojIH0gZWxzZXsKIyAgICAgdHJ5Q2F0Y2goewojICAgICAgICAgbmEuZnVuYyA8LSBnZXQobmEuZnVuY3Rpb24pCiMgICAgIH0sIHdhcm5pbmc9ZnVuY3Rpb24od2Fybil7CiMgICAgICAgICB3YXJuaW5nKHdhcm4pCiMgICAgIH0sIGVycm9yPWZ1bmN0aW9uKGVycil7CiMgICAgICAgICBzdG9wKHBhc3RlMCgiTkEgZnVuY3Rpb24gIiwgbmEuZnVuY3Rpb24sICIgbm90IHJlY29nbmlzZWQiKSkKIyAgICAgfSwgZmluYWxseT17CiMgICAgIH0pCiMgfQojIAojIG4uZGEgPC0gc3VtKG5hLmZ1bmMoZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIpKQojIAojIGlmKChuY29sKG5ob29kQWRqYWNlbmN5KHgpKSA9PSBsZW5ndGgobmhvb2RzKHgpKSkgJiBpc0ZBTFNFKGNvbXB1dGUubmV3KSl7CiMgICAgIG1lc3NhZ2UoIm5ob29kQWRqYWNlbmN5IGZvdW5kIC0gdXNpbmcgZm9yIG5ob29kIGdyb3VwaW5nIikKIyAgICAgbmhzLmRhLmdyIDwtIC5ncm91cF9uaG9vZHNfZnJvbV9hZGphY2VuY3kobmhzPW5ob29kcyh4KSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmhvb2QuYWRqPW5ob29kQWRqYWNlbmN5KHgpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYS5yZXM9ZGEucmVzLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5kYT1kYS5yZXMkU3BhdGlhbEZEUiA8IGRhLmZkciwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGZjLnRocmVzaG9sZD1sZmMudGhyZXNob2xkLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPW1lcmdlLmRpc2NvcmQsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9b3ZlcmxhcCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2V0Lm5ob29kcz1zdWJzZXQubmhvb2RzKQojIH0gZWxzZXsKIyAgICAgbmhzLmRhLmdyIDwtIC5ncm91cF9uaG9vZHNfYnlfb3ZlcmxhcChuaG9vZHMoeCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGEucmVzPWRhLnJlcywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5kYT1kYS5yZXMkU3BhdGlhbEZEUiA8IGRhLmZkciwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPW1lcmdlLmRpc2NvcmQsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcmxhcD1vdmVybGFwLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdHM9Yml0cywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxscz1zZXFfbGVuKG5jb2woeCkpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNldC5uaG9vZHM9c3Vic2V0Lm5ob29kcykgIyByZXR1cm5zIGEgdmVjdG9yIGdyb3VwIHZhbHVlcyBmb3IgZWFjaCBuaG9vZAojICAgICAgICAgIyBuaHMuZGEuZ3IgPC0gLmdyb3VwX25ob29kc19ieV9vdmVybGFwKG5ob29kcyh4KSwKIyAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYS5yZXM9ZGEucmVzLAojICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLmRhPWRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyLAojICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlLmRpc2NvcmQ9bWVyZ2UuZGlzY29yZCwKIyAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIyAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybGFwPW92ZXJsYXAsCiMgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0cz1iaXRzLAojICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxzPXNlcV9sZW4obmNvbCh4KSksCiMgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2V0Lm5ob29kcz1zdWJzZXQubmhvb2RzKQojICAgICB9CiMgCiMgbmhvb2QuZ3IgPC0gdW5pcXVlKG5ocy5kYS5ncikKIyAjIHBlcmZvcm0gREdFIF93aXRoaW5fIGVhY2ggZ3JvdXAgb2YgY2VsbHMgdXNpbmcgdGhlIGlucHV0IGRlc2lnbiBtYXRyaXgKIyBtZXNzYWdlKHBhc3RlMCgiTmhvb2RzIGFnZ3JlZ2F0ZWQgaW50byAiLCBsZW5ndGgobmhvb2QuZ3IpLCAiIGdyb3VwcyIpKQojIAojIGZha2UubWV0YSA8LSBkYXRhLmZyYW1lKCJDZWxsSUQiPWNvbG5hbWVzKHgpLCAiTmhvb2QuR3JvdXAiPXJlcChOQSwgbmNvbCh4KSkpCiMgcm93bmFtZXMoZmFrZS5tZXRhKSA8LSBmYWtlLm1ldGEkQ2VsbElECiMgCiMgZm9yKGkgaW4gc2VxX2Fsb25nKG5ob29kLmdyKSl7CiMgICAgIG5ob29kLnggPC0gbmhzLmRhLmdyID09IG5ob29kLmdyW2ldCiMgICAgICMgZ2V0IHRoZSBuaG9vZHMKIyAgICAgbmhzIDwtIG5ob29kcyh4KQojICAgICBpZighaXMubnVsbChzdWJzZXQubmhvb2RzKSl7CiMgICAgICAgICBuaHMgPC0gbmhzW3N1YnNldC5uaG9vZHNdCiMgICAgIH0KIyAKIyAgICAgaWYoIWFueShpcy5uYShmYWtlLm1ldGFbdW5saXN0KG5oc1tuaG9vZC54XSksXSROaG9vZC5Hcm91cCkpKXsKIyAgICAgICAgIGZha2UubWV0YVt1bmxpc3QobmhzW25ob29kLnhdKSxdJE5ob29kLkdyb3VwWyFpcy5uYShmYWtlLm1ldGFbdW5saXN0KG5oc1tuaG9vZC54XSksXSROaG9vZC5Hcm91cCldIDwtIE5BCiMgICAgICAgICB9IGVsc2V7CiMgICAgICAgICAgICAgZmFrZS5tZXRhW3VubGlzdChuaHNbbmhvb2QueF0pLF0kTmhvb2QuR3JvdXAgPC0gbmhvb2QuZ3JbaV0KIyAgICAgICAgIH0KIyB9CiMgCiMgIyBvbmx5IGNvbXBhcmUgYWdhaW5zdCB0aGUgb3RoZXIgREEgbmVpZ2hib3VyaG9vZHMKIyB4IDwtIHhbLCAhaXMubmEoZmFrZS5tZXRhJE5ob29kLkdyb3VwKV0KIyBmYWtlLm1ldGEgPC0gZmFrZS5tZXRhWyFpcy5uYShmYWtlLm1ldGEkTmhvb2QuR3JvdXApLCBdCiMgCiMgaWYoIWlzLm51bGwoc3Vic2V0LnJvdykpewojICAgICB4IDwtIHhbc3Vic2V0LnJvdywgLCBkcm9wPUZBTFNFXQojIH0KIyAKIyBmYWtlLm1ldGFbLCJzYW1wbGVfaWQiXSA8LSBzYXBwbHkoc3Ryc3BsaXQoZmFrZS5tZXRhJENlbGxJRCwgIl8iKSwgZnVuY3Rpb24oeCkgcGFzdGUoeFsxXSwgeFsyXSwgc2VwPSJfIikpCiMgZmFrZS5tZXRhWywnc2FtcGxlX2dyb3VwJ10gPC0gcGFzdGUoZmFrZS5tZXRhWywic2FtcGxlX2lkIl0sIGZha2UubWV0YVssIk5ob29kLkdyb3VwIl0sIHNlcD0iXyIpCgpzYW1wbGVfZ3JfbWF0IDwtIG1hdHJpeCgwLCBucm93PW5yb3coZmFrZS5tZXRhKSwgbmNvbD1sZW5ndGgodW5pcXVlKGZha2UubWV0YSRzYW1wbGVfZ3JvdXApKSkKY29sbmFtZXMoc2FtcGxlX2dyX21hdCkgPC0gdW5pcXVlKGZha2UubWV0YSRzYW1wbGVfZ3JvdXApCnJvd25hbWVzKHNhbXBsZV9ncl9tYXQpIDwtIHJvd25hbWVzKGZha2UubWV0YSkKCmZvciAocyBpbiBjb2xuYW1lcyhzYW1wbGVfZ3JfbWF0KSkgewogIHNhbXBsZV9ncl9tYXRbd2hpY2goZmFrZS5tZXRhJHNhbXBsZV9ncm91cCA9PSBzKSxzXSA8LSAxICAKfQoKZXhwcnMgPC0gYXNzYXkoeCwgYXNzYXkpCgpleHByc19zbXAgPC0gbWF0cml4KDAsIG5yb3c9bnJvdyhleHBycyksIG5jb2w9bmNvbChzYW1wbGVfZ3JfbWF0KSkKZm9yIChpIGluIDE6bmNvbChzYW1wbGVfZ3JfbWF0KSl7CiAgaWYgKHN1bShzYW1wbGVfZ3JfbWF0WyxpXSkgPiAxKSB7CiAgICBleHByc19zbXBbLGldIDwtIHJvd1N1bXMoZXhwcnNbLHdoaWNoKHNhbXBsZV9ncl9tYXRbLGldID4gMCldKSAgCiAgfSBlbHNlIHsKICAgIGV4cHJzX3NtcFssaV0gPC0gZXhwcnNbLHdoaWNoKHNhbXBsZV9ncl9tYXRbLGldID4gMCldCiAgfQp9CnJvd25hbWVzKGV4cHJzX3NtcCkgPC0gcm93bmFtZXMoZXhwcnMpCmNvbG5hbWVzKGV4cHJzX3NtcCkgPC0gY29sbmFtZXMoc2FtcGxlX2dyX21hdCkKCnNtcF9tZXRhIDwtIGRpc3RpbmN0KGZha2UubWV0YSwgc2FtcGxlX2dyb3VwLCBOaG9vZC5Hcm91cCkKcm93bmFtZXMoc21wX21ldGEpIDwtIHNtcF9tZXRhWywic2FtcGxlX2dyb3VwIl0KCm1hcmtlci5saXN0IDwtIGxpc3QoKQppLmNvbnRyYXN0IDwtIGMoIlRlc3RUZXN0IC0gVGVzdFJlZiIpICMgYWx3YXlzIHVzZSBjb250cmFzdHMgZm9yIHRoaXMKCiAgIyAjIGlmIHRoZXJlIGlzIG9ubHkgMSBncm91cCwgdGhlbiBuZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbCBuZWlnaGJvdXJob29kcwogICMgIyBhcmUgbm90IGluIHRoaXMgZ3JvdXAgLSBvdGhlcndpc2UgY2FuJ3QgZG8gYW55IERHRSB0ZXN0aW5nCiAgIyBpZihsZW5ndGgobmhvb2QuZ3IpID09IDEpewogICMgICAgIGlmKHN1bShmYWtlLm1ldGEkTmhvb2QuR3JvdXAgPT0gbmhvb2QuZ3JbMV0pID09IG5yb3coZmFrZS5tZXRhKSl7CiAgIyAgICAgICAgIHdhcm5pbmcoIkFsbCBncmFwaCBuZWlnaGJvdXJob29kcyBhcmUgaW4gdGhlIHNhbWUgZ3JvdXAgLSBjYW5ub3QgcGVyZm9ybSBER0UgdGVzdGluZy4gUmV0dXJuaW5nIE5VTEwiKQogICMgICAgICAgICByZXR1cm4oTlVMTCkKICAjICAgICB9CiAgIyB9CgpuaG9vZC5nciA8LSB1bmlxdWUoZmFrZS5tZXRhWywiTmhvb2QuR3JvdXAiXSkKICBmb3IoaSBpbiBzZXFfYWxvbmcobmhvb2QuZ3IpKXsKICAgICAgaS5tZXRhIDwtIHNtcF9tZXRhCiAgICAgIGkubWV0YSRUZXN0IDwtICJSZWYiCiAgICAgIGkubWV0YSRUZXN0W3NtcF9tZXRhJE5ob29kLkdyb3VwID09IG5ob29kLmdyW2ldXSA8LSAiVGVzdCIKICAgICAgaWYobmNvbChleHByc19zbXApID4gMSAmIG5yb3coaS5tZXRhKSA+IDEpewogICAgICAgICAgaS5kZXNpZ24gPC0gYXMuZm9ybXVsYSgiIH4gMCArIFRlc3QiKQogICAgICAgICAgaS5tb2RlbCA8LSBtb2RlbC5tYXRyaXgoaS5kZXNpZ24sIGRhdGE9aS5tZXRhKQogICAgICAgICAgcm93bmFtZXMoaS5tb2RlbCkgPC0gcm93bmFtZXMoaS5tZXRhKQogICAgICB9CgogICAgICBzaW5rKGZpbGU9Ii9kZXYvbnVsbCIpCiAgICAgIGdjKCkKICAgICAgc2luayhmaWxlPU5VTEwpCgogICAgICBpZihhc3NheSA9PSAibG9nY291bnRzIil7CiAgICAgICAgICBpLnJlcyA8LSAucGVyZm9ybV9sb2dub3JtYWxfZGdlKGV4cHJzX3NtcCwgaS5tb2RlbCwgbW9kZWwuY29udHJhc3RzPWkuY29udHJhc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmUub2Zmc2V0PWdlbmUub2Zmc2V0KQogICAgICB9IGVsc2UgaWYoYXNzYXkgPT0gImNvdW50cyIpewogICAgICAgICAgaS5yZXMgPC0gLnBlcmZvcm1fY291bnRzX2RnZShleHByc19zbXAsIGkubW9kZWwsIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lLm9mZnNldD1nZW5lLm9mZnNldCkKICAgICAgICAgIGNvbG5hbWVzKGkucmVzKVtuY29sKGkucmVzKV0gPC0gImFkai5QLlZhbCIKICAgICAgfSBlbHNlewogICAgICAgICAgd2FybmluZygiQXNzYXkgdHlwZSBpcyBub3QgY291bnRzIG9yIGxvZ2NvdW50cyAtIGFzc3VtaW5nIChsb2cpLW5vcm1hbCBkaXN0cmlidXRpb24uIFVzZSB0aGVzZSByZXN1bHRzIGF0IHlvdXIgcGVyaWwiKQogICAgICAgICAgaS5yZXMgPC0gLnBlcmZvcm1fbG9nbm9ybWFsX2RnZShleHByc19zbXAsIGkubW9kZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lLm9mZnNldD1nZW5lLm9mZnNldCkKICAgICAgfQogICAgICAKICAgICAgCiAgICAgIGkucmVzJGFkai5QLlZhbFtpcy5uYShpLnJlcyRhZGouUC5WYWwpXSA8LSAxCiAgICAgIGkucmVzJGxvZ0ZDW2lzLmluZmluaXRlKGkucmVzJGxvZ0ZDKV0gPC0gMAogICAgICAKICAgICAgaS5yZXMgPC0gaS5yZXNbLCBjKCJsb2dGQyIsICJhZGouUC5WYWwiKV0KICAgICAgY29sbmFtZXMoaS5yZXMpIDwtIHBhc3RlKGNvbG5hbWVzKGkucmVzKSwgbmhvb2QuZ3JbaV0sIHNlcD0iXyIpCiAgICAgIG1hcmtlci5saXN0W1twYXN0ZTAobmhvb2QuZ3JbaV0pXV0gPC0gaS5yZXMKICB9CgogIG1hcmtlci5kZiA8LSBkby5jYWxsKGNiaW5kLmRhdGEuZnJhbWUsIG1hcmtlci5saXN0KQogIGNvbG5hbWVzKG1hcmtlci5kZikgPC0gZ3N1Yihjb2xuYW1lcyhtYXJrZXIuZGYpLCBwYXR0ZXJuPSJeWzAtOV0rXFwuIiwgcmVwbGFjZW1lbnQ9IiIpCiAgbWFya2VyLmRmJEdlbmVJRCA8LSByb3duYW1lcyhpLnJlcykKYGBgCgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbWFya2Vyc19kZiA8LSAtLT4KPCEtLSAgIGZpbmROaG9vZE1hcmtlcnMoeCA9IGxpdmVyX21pbG8sIC0tPgo8IS0tICAgZGEucmVzID0gbWlsb19yZXMsIC0tPgo8IS0tICAgZGEuZmRyPTAuMSwgLS0+CjwhLS0gICBhc3NheT0iY291bnRzIiwgLS0+CjwhLS0gICBhZ2dyZWdhdGUuc2FtcGxlcyA9IFRSVUUsIHNhbXBsZV9jb2wgPSAic2FtcGxlX2lkIiwgLS0+CjwhLS0gICBvdmVybGFwPTEsIC0tPgo8IS0tICAgbGZjLnRocmVzaG9sZCA9IDAuMSwgLS0+CjwhLS0gICBtZXJnZS5kaXNjb3JkPUZBTFNFLCAtLT4KPCEtLSAgIHN1YnNldC5yb3cgPSBodmdzLCAtLT4KPCEtLSAgIGdlbmUub2Zmc2V0PUZBTFNFLCAtLT4KPCEtLSAgIHJldHVybi5ncm91cHM9RkFMU0UsIC0tPgo8IS0tICAgc3Vic2V0Lm5ob29kcyA9IHN0cl9kZXRlY3QobWlsb19yZXMkYW5ub3RhdGlvbl9pbmRlcHRoLCAiRW5kbyIpLCAtLT4KPCEtLSAgIG5hLmZ1bmN0aW9uPSJuYS5wYXNzIiwgLS0+CjwhLS0gICBjb21wdXRlLm5ldz1GQUxTRSwgLS0+CjwhLS0gICBiaXRzPUZBTFNFKSAtLT4KPCEtLSBgYGAgLS0+CgojIyMjIFNpZ25pZmljYW50IERHRSBnZW5lcyAoRkRSIDEwJSkKCmBgYHtyfQptYXJrZXIuZGZbbWFya2VyLmRmJGFkai5QLlZhbF8xIDwgMC4wNSxdCmBgYAoKCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSB4ID0gbGl2ZXJfbWlsbyAtLT4KPCEtLSBkYS5yZXMgPSBtaWxvX3JlcyAtLT4KPCEtLSBkYS5mZHI9MC4xIC0tPgo8IS0tIGFzc2F5PSJsb2djb3VudHMiIC0tPgo8IS0tIG92ZXJsYXA9MSAtLT4KPCEtLSBsZmMudGhyZXNob2xkPTAuMSAtLT4KPCEtLSBtZXJnZS5kaXNjb3JkPUZBTFNFIC0tPgo8IS0tIHN1YnNldC5yb3cgPSBlbmRvX2h2Z3MgLS0+CjwhLS0gZ2VuZS5vZmZzZXQ9VFJVRSAtLT4KPCEtLSByZXR1cm4uZ3JvdXBzPVRSVUUgLS0+CjwhLS0gc3Vic2V0Lm5ob29kcyA9IHN0cl9kZXRlY3QobWlsb19yZXMkYW5ub3RhdGlvbl9pbmRlcHRoLCAiRW5kbyIpIC0tPgo8IS0tIG5hLmZ1bmN0aW9uPSJuYS5wYXNzIiAtLT4KPCEtLSBjb21wdXRlLm5ldz1GQUxTRSAtLT4KCgo8IS0tIGlmKCFpcyh4LCAiTWlsbyIpKXsgLS0+CjwhLS0gICAgIHN0b3AoIlVucmVjb2duaXNlZCBpbnB1dCB0eXBlIC0gbXVzdCBiZSBvZiBjbGFzcyBNaWxvIikgLS0+CjwhLS0gfSBlbHNlIGlmKGFueSghYXNzYXkgJWluJSBhc3NheU5hbWVzKHgpKSl7IC0tPgo8IS0tICAgICBzdG9wKHBhc3RlMCgiVW5yZWNvZ25pc2VkIGFzc2F5IHNsb3Q6ICIsIGFzc2F5KSkgLS0+CjwhLS0gfSAtLT4KCjwhLS0gaWYoaXMubnVsbChuYS5mdW5jdGlvbikpeyAtLT4KPCEtLSAgICAgd2FybmluZygiTlVMTCBwYXNzZWQgdG8gbmEuZnVuY3Rpb24sIHVzaW5nIG5hLnBhc3MiKSAtLT4KPCEtLSAgICAgbmEuZnVuYyA8LSBnZXQoIm5hLnBhc3MiKSAtLT4KPCEtLSB9IGVsc2V7IC0tPgo8IS0tICAgICB0cnlDYXRjaCh7IC0tPgo8IS0tICAgICAgICAgbmEuZnVuYyA8LSBnZXQobmEuZnVuY3Rpb24pIC0tPgo8IS0tICAgICB9LCB3YXJuaW5nPWZ1bmN0aW9uKHdhcm4peyAtLT4KPCEtLSAgICAgICAgIHdhcm5pbmcod2FybikgLS0+CjwhLS0gICAgIH0sIGVycm9yPWZ1bmN0aW9uKGVycil7IC0tPgo8IS0tICAgICAgICAgc3RvcChwYXN0ZTAoIk5BIGZ1bmN0aW9uICIsIG5hLmZ1bmN0aW9uLCAiIG5vdCByZWNvZ25pc2VkIikpIC0tPgo8IS0tICAgICB9LCBmaW5hbGx5PXsgLS0+CjwhLS0gICAgIH0pIC0tPgo8IS0tIH0gLS0+Cgo8IS0tIG4uZGEgPC0gc3VtKG5hLmZ1bmMoZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIpKSAtLT4KPCEtLSBpZighaXMubmEobi5kYSkgJiBuLmRhID09IDApeyAtLT4KPCEtLSAgICAgc3RvcCgiTm8gREEgbmVpZ2hib3VyaG9vZHMgZm91bmQiKSAtLT4KPCEtLSB9IC0tPgoKPCEtLSBpZihhbnkoaXMubmEoZGEucmVzJFNwYXRpYWxGRFIpKSl7IC0tPgo8IS0tICAgICB3YXJuaW5nKCJOQSB2YWx1ZXMgZm91bmQgaW4gU3BhdGlhbEZEUiB2ZWN0b3IiKSAtLT4KPCEtLSB9IC0tPgoKPCEtLSBtZXNzYWdlKHBhc3RlMCgiRm91bmQgIiwgbi5kYSwgIiBEQSBuZWlnaGJvdXJob29kcyBhdCBGRFIgIiwgZGEuZmRyKjEwMCwgIiUiKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbmhzID0gbmhvb2RzKHgpIC0tPgo8IS0tIG5ob29kLmFkaiA9IG5ob29kQWRqYWNlbmN5KHgpIC0tPgo8IS0tIGRhLnJlcyA9IG1pbG9fcmVzIC0tPgo8IS0tIGlzLmRhID0gZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIgLS0+CjwhLS0gICAgICMgIyBhc3N1bWUgb3JkZXIgb2YgbmhzIGlzIHRoZSBzYW1lIGFzIG5ob29kLmFkaiAtLT4KPCEtLSAgICAgIyBpZighaXMubnVsbChzdWJzZXQubmhvb2RzKSl7IC0tPgo8IS0tICAgICAjICAgICBpZihtb2RlKHN1YnNldC5uaG9vZHMpICVpbiUgYygiY2hhcmFjdGVyIiwgImxvZ2ljYWwiLCAibnVtZXJpYyIpKXsgLS0+CjwhLS0gICAgICMgICAgICAgICAjIGZvcmNlIHVzZSBvZiBsb2dpY2FscyBmb3IgY29uc2lzdGVuY3kgLS0+CjwhLS0gICAgICMgICAgICAgICBpZihtb2RlKHN1YnNldC5uaG9vZHMpICVpbiUgYygiY2hhcmFjdGVyIiwgIm51bWVyaWMiKSl7IC0tPgo8IS0tICAgICAjICAgICAgICAgICAgIHN1Yi5sb2cgPC0gbmFtZXMobmhzKSAlaW4lIHN1YnNldC5uaG9vZHMgLS0+CjwhLS0gICAgICMgICAgICAgICB9IGVsc2V7IC0tPgo8IS0tICAgICAjICAgICAgICAgICAgIHN1Yi5sb2cgPC0gc3Vic2V0Lm5ob29kcyAtLT4KPCEtLSAgICAgIyAgICAgICAgIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICAgICAgICAgbmhvb2QuYWRqIDwtIG5ob29kLmFkaltzdWIubG9nLCBzdWIubG9nXSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgICAgICAgICBpZihsZW5ndGgoaXMuZGEpID09IGxlbmd0aChuaHMpKXsgLS0+CjwhLS0gICAgICMgICAgICAgICAgICAgbmhzIDwtIG5oc1tzdWIubG9nXSAtLT4KPCEtLSAgICAgIyAgICAgICAgICAgICBpcy5kYSA8LSBpcy5kYVtzdWIubG9nXSAtLT4KPCEtLSAgICAgIyAgICAgICAgICAgICBkYS5yZXMgPC0gZGEucmVzW3N1Yi5sb2csIF0gLS0+CjwhLS0gICAgICMgICAgICAgICB9IGVsc2V7IC0tPgo8IS0tICAgICAjICAgICAgICAgICAgIHN0b3AoIlN1YnNldHRpbmcgYGlzLmRhYCB2ZWN0b3IgbGVuZ3RoIGRvZXMgbm90IGVxdWFsIG5ob29kcyBsZW5ndGgiKSAtLT4KPCEtLSAgICAgIyAgICAgICAgIH0gLS0+CjwhLS0gICAgICMgICAgIH0gZWxzZXsgLS0+CjwhLS0gICAgICMgICAgICAgICBzdG9wKHBhc3RlMCgiSW5jb3JyZWN0IHN1YnNldHRpbmcgdmVjdG9yIHByb3ZpZGVkOiIsIGNsYXNzKHN1YnNldC5uaG9vZHMpKSkgLS0+CjwhLS0gICAgICMgICAgIH0gLS0+CjwhLS0gICAgICMgfSBlbHNleyAtLT4KPCEtLSAgICAgIyAgICAgaWYobGVuZ3RoKGlzLmRhKSAhPSBuY29sKG5ob29kLmFkaikpeyAtLT4KPCEtLSAgICAgIyAgICAgICAgIHN0b3AoIlN1YnNldHRpbmcgYGlzLmRhYCB2ZWN0b3IgbGVuZ3RoIGlzIG5vdCB0aGUgc2FtZSBkaW1lbnNpb24gYXMgYWRqYWNlbmN5IikgLS0+CjwhLS0gICAgICMgICAgIH0gLS0+CjwhLS0gICAgICMgfSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICMjIGNoZWNrIGZvciBjb25jb3JkYW50IHNpZ25zIC0gYXNzdW1lIG9yZGVyIGlzIHRoZSBzYW1lIGFzIG5ob29kcyAtLT4KPCEtLSAgICAgIyBpZihpc0ZBTFNFKG1lcmdlLmRpc2NvcmQpKXsgLS0+CjwhLS0gICAgICMgICAgIG5vbnoubmhzIDwtIGNvbFN1bXMobmhvb2QuYWRqKSA+IDAgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzIDwtIGV4cGFuZC5ncmlkKGMoMTpsZW5ndGgobmhzW25vbnoubmhzXSkpLCBjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSkgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzWyJhZGoiXSA8LSBzYXBwbHkoMTpucm93KGxsX25hbWVzKSwgZnVuY3Rpb24oeCkgbmhvb2QuYWRqW2xsX25hbWVzW3gsMV0sbGxfbmFtZXNbeCwyXV0pIC0tPgo8IS0tICAgICAjICAgICBub256LnBhaXJzIDwtIGxsX25hbWVzWywiYWRqIl0gPiAwIC0tPgo8IS0tICAgICAjICAgICAgLS0+CjwhLS0gICAgICMgICAgIGNvbmNvcmQuc2lnbiA8LSBzYXBwbHkoKDE6bnJvdyhsbF9uYW1lcykpW25vbnoucGFpcnNdLCBmdW5jdGlvbih4KSBzaWduKGRhLnJlc1tub256Lm5ocywgXVthcy5udW1lcmljKGxsX25hbWVzW3gsIDFdKSwgXSRsb2dGQykgPT0gLS0+CjwhLS0gICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24oZGEucmVzW25vbnoubmhzLF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAyXSksIF0kbG9nRkMpKSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzWywiYWRqIl1bbm9uei5wYWlyc11bIWNvbmNvcmQuc2lnbl0gPC0gMCAtLT4KPCEtLSAgICAgIyAgICAgbmhvb2QuYWRqW25vbnoubmhzLCBub256Lm5oc10gPC0gbGxfbmFtZXNbLCAiYWRqIl0gLS0+CjwhLS0gICAgICMgfSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgaWYob3ZlcmxhcCA+IDEpeyAtLT4KPCEtLSAgICAgIyAgICAgIyBsb29wIG92ZXIgYWRqIGRpbWVuc2lvbnMgYW5kIG1hc2sgb3V0IGNlbGxzIHdpdGggaW5zdWZmaWNpZW50IG92ZXJsYXBwaW5nIGNlbGxzIC0tPgo8IS0tICAgICAjICAgICBub256Lm5ocyA8LSBjb2xTdW1zKG5ob29kLmFkaikgPiAwIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lcyA8LSBleHBhbmQuZ3JpZChjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSwgYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSkpIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lc1siYWRqIl0gPC0gc2FwcGx5KDE6bnJvdyhsbF9uYW1lcyksIGZ1bmN0aW9uKHgpIG5ob29kLmFkaltsbF9uYW1lc1t4LDFdLGxsX25hbWVzW3gsMl1dKSAtLT4KPCEtLSAgICAgIyAgICAgbm9uei5wYWlycyA8LSBsbF9uYW1lc1ssImFkaiJdID4gMCAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXNbbm9uei5wYWlycywiYWRqIl0gPC0gaWZlbHNlKGxsX25hbWVzW25vbnoucGFpcnMsImFkaiJdIDwgb3ZlcmxhcCwgMCwgbGxfbmFtZXNbbm9uei5wYWlycywiYWRqIl0gKSAtLT4KPCEtLSAgICAgIyAgICAgbmhvb2QuYWRqW25vbnoubmhzLCBub256Lm5oc10gPC0gbGxfbmFtZXNbLCAiYWRqIl0gLS0+CjwhLS0gICAgICMgfSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgaWYoIWlzLm51bGwobGZjLnRocmVzaG9sZCkpeyAtLT4KPCEtLSAgICAgIyAgICAgbm9uei5uaHMgPC0gY29sU3VtcyhuaG9vZC5hZGopID4gMCAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXMgPC0gZXhwYW5kLmdyaWQoYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSksIGMoMTpsZW5ndGgobmhzW25vbnoubmhzXSkpKSAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXNbImFkaiJdIDwtIHNhcHBseSgxOm5yb3cobGxfbmFtZXMpLCBmdW5jdGlvbih4KSBuaG9vZC5hZGpbbGxfbmFtZXNbeCwxXSxsbF9uYW1lc1t4LDJdXSkgLS0+CjwhLS0gICAgICMgICAgIG5vbnoucGFpcnMgPC0gbGxfbmFtZXNbLCJhZGoiXSA+IDAgLS0+CjwhLS0gICAgICMgICAgICAtLT4KPCEtLSAgICAgIyAgICAgIyBzZXQgYWRqYWNlbmN5IHRvIDAgZm9yIG5ob29kcyB3aXRoIGxmYyA8IHRocmVzaG9sZCAtLT4KPCEtLSAgICAgIyAgICAgbGZjLnBhc3MgPC0gc2FwcGx5KCgxOm5yb3cobGxfbmFtZXMpKVtub256LnBhaXJzXSwgZnVuY3Rpb24oeCkgKGFicyhkYS5yZXNbbm9uei5uaHMsIF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAxXSksIF0kbG9nRkMpID49IGxmYy50aHJlc2hvbGQpICYgLS0+CjwhLS0gICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFicyhkYS5yZXNbbm9uei5uaHMsIF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAyXSksIF0kbG9nRkMpID49IGxmYy50aHJlc2hvbGQpKSAtLT4KPCEtLSAgICAgIyAgICAgIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lc1ssImFkaiJdW25vbnoucGFpcnNdWyFsZmMucGFzc10gPC0gMCAtLT4KPCEtLSAgICAgIyAgICAgbmhvb2QuYWRqW25vbnoubmhzLCBub256Lm5oc10gPC0gbGxfbmFtZXNbLCAiYWRqIl0gLS0+CjwhLS0gICAgICMgfSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgIyBiaW5hcmlzZSAtLT4KPCEtLSAgICAgIyBuaG9vZC5hZGogPC0gYXMubWF0cml4KChuaG9vZC5hZGogPiAwKSArIDApIC0tPgo8IS0tICAgICAjICAtLT4KPCEtLSAgICAgIyBuLmRpbSA8LSBuY29sKG5ob29kLmFkaikgLS0+CjwhLS0gICAgICMgaWYoIWlzU3ltbWV0cmljKG5ob29kLmFkaikpeyAtLT4KPCEtLSAgICAgIyAgICAgc3RvcCgiT3ZlcmxhcCBtYXRyaXggaXMgbm90IHN5bW1ldHJpYyIpIC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjIGlmKG5yb3cobmhvb2QuYWRqKSAhPSBuY29sKG5ob29kLmFkaikpeyAtLT4KPCEtLSAgICAgIyAgICAgc3RvcCgiTm9uLXNxdWFyZSBkaXN0YW5jZSBtYXRyaXggLSBjaGVjayBuaG9vZCBzdWJzZXR0aW5nIikgLS0+CjwhLS0gICAgICMgfSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgZyA8LSBncmFwaF9mcm9tX2FkamFjZW5jeV9tYXRyaXgobmhvb2QuYWRqLCBtb2RlPSJ1bmRpcmVjdGVkIiwgZGlhZz1GQUxTRSkgLS0+CjwhLS0gICAgICMgZ3JvdXBzIDwtIGNvbXBvbmVudHMoZykkbWVtYmVyc2hpcCAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgIyBvbmx5IGtlZXAgdGhlIGdyb3VwcyB0aGF0IGNvbnRhaW4gPj0gMSBEQSBuZWlnaGJvdXJob29kcyAtLT4KPCEtLSAgICAgIyBrZWVwLmdyb3VwcyA8LSBpbnRlcnNlY3QodW5pcXVlKGdyb3Vwc1tpcy5kYV0pLCB1bmlxdWUoZ3JvdXBzKSkgLS0+CjwhLS0gLmdyb3VwX25ob29kc19mcm9tX2FkamFjZW5jeSA8LSBmdW5jdGlvbih4LCBkYS5yZXMsIGlzLmRhLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlLmRpc2NvcmQ9RkFMU0UsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGZjLnRocmVzaG9sZD1OVUxMLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9MSwgc3Vic2V0Lm5ob29kcz1OVUxMKXsgLS0+Cgo8IS0tICAgICBpZihpcy5udWxsKG5hbWVzKG5ocykpKXsgLS0+CjwhLS0gICAgICAgICB3YXJuaW5nKCJObyBuYW1lcyBhdHRyaWJ1dGVkIHRvIG5ob29kcy4gQ29udmVydGluZyBpbmRpY2VzIHRvIG5hbWVzIikgLS0+CjwhLS0gICAgICAgICBuYW1lcyhuaHMpIDwtIGFzLmNoYXJhY3RlcihjKDE6bGVuZ3RoKG5ocykpKSAtLT4KPCEtLSAgICAgfSAtLT4KCjwhLS0gICBuaF9ncmFwaCA8LSBuaG9vZEdyYXBoKHgpIC0tPgo8IS0tICAgIyMgQ2hhbmdlIG5hbWVzIGZyb20gbmhvb2RJbmRleCB0byBuaG9vZE51bWJlciAtLT4KPCEtLSAgIFYobmhfZ3JhcGgpJG5hbWUgPC0gbWF0Y2goVihuaF9ncmFwaCkkbmFtZSwgdW5saXN0KG5ob29kSW5kZXgoeCkpKSAtLT4KCjwhLS0gICBtYXgoYXMubnVtZXJpYyhWKG5oX2dyYXBoKSRuYW1lKSkgLS0+Cgo8IS0tICAgaWYoIWlzLm51bGwoc3Vic2V0Lm5ob29kcykpeyAtLT4KPCEtLSAgICAgZGEucmVzIDwtIGRhLnJlc1tzdWJzZXQubmhvb2RzLF0gICAtLT4KPCEtLSAgIH0gLS0+Cgo8IS0tICAga2VlcC5uaG9vZHMgPC0gZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIgJiAgLS0+CjwhLS0gICAgIGFicyhkYS5yZXMkbG9nRkMpID4gbGZjLnRocmVzaG9sZCAtLT4KCjwhLS0gIyB1bmxpc3Qobmhvb2RJbmRleCh4KVtzdWJzZXQubmhvb2RzXSkgLS0+CjwhLS0gIyBhcy5udW1lcmljKFYobmhfZ3JhcGgpJG5hbWUpICVpbiUgdW5saXN0KG5ob29kSW5kZXgoeClbc3Vic2V0Lm5ob29kc10pICYgLS0+CjwhLS0gIyAgIChkYS5yZXMkU3BhdGlhbEZEUiA8IGRhLmZkcikgLS0+Cgo8IS0tICAgbmhfZ3JhcGggPC0gIC0tPgo8IS0tICAgICBpZ3JhcGg6OmluZHVjZWRfc3ViZ3JhcGgobmhfZ3JhcGgsICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZHMgPSBhcy5jaGFyYWN0ZXIoZGEucmVzJE5ob29kW2tlZXAubmhvb2RzXSkgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHZpZHMgPSB3aGljaChhcy5udW1lcmljKFYobmhfZ3JhcGgpJG5hbWUpICVpbiUgdW5saXN0KG5ob29kSW5kZXgoeClbZGEucmVzW2tlZXAubmhvb2RzLCJOaG9vZCJdXSkpIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAtLT4KPCEtLSAgIGdyb3VwcyA8LSBjb21wb25lbnRzKG5oX2dyYXBoKSRtZW1iZXJzaGlwIC0tPgo8IS0tICAga2VlcC5ncm91cHMgPC0gaW50ZXJzZWN0KHVuaXF1ZShncm91cHNbaXMuZGFdKSwgdW5pcXVlKGdyb3VwcykpIC0tPgoKCgo8IS0tICAgcmV0dXJuKGdyb3Vwc1tncm91cHMgJWluJSBrZWVwLmdyb3Vwc10pIC0tPgo8IS0tIH0gLS0+CgoKPCEtLSBkYS5yZXMgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGtlZXA9a2VlcC5uaG9vZHMpICU+JSAtLT4KPCEtLSAgIGdncGxvdChhZXMobG9nRkMsIC1sb2cxMChTcGF0aWFsRkRSKSwgY29sb3I9a2VlcCkpICsgLS0+CjwhLS0gICBnZW9tX3BvaW50KCkgLS0+CjwhLS0gZ2dyYXBoKG5oX2dyYXBoKSArIGdlb21fZWRnZV9saW5rMigpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBsZmMudGhyZXNob2xkID0gMCAtLT4KPCEtLSBpZighaXMubnVsbChuaG9vZEFkamFjZW5jeSh4KSkgJiBpc0ZBTFNFKGNvbXB1dGUubmV3KSl7IC0tPgo8IS0tICAgICBtZXNzYWdlKCJuaG9vZEFkamFjZW5jeSBmb3VuZCAtIHVzaW5nIGZvciBuaG9vZCBncm91cGluZyIpIC0tPgo8IS0tICAgICBuaHMuZGEuZ3IgPC0gLmdyb3VwX25ob29kc19mcm9tX2FkamFjZW5jeSh4LCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGEucmVzPW1pbG9fcmVzLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMuZGE9ZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQubmhvb2RzID0gc3Vic2V0Lm5ob29kcywgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlLmRpc2NvcmQ9bWVyZ2UuZGlzY29yZCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9b3ZlcmxhcCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxmYy50aHJlc2hvbGQ9bGZjLnRocmVzaG9sZCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAtLT4KPCEtLSB9IGVsc2V7IC0tPgo8IS0tICAgICBuaHMuZGEuZ3IgPC0gLmdyb3VwX25ob29kc19ieV9vdmVybGFwKG5ob29kcyh4KSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGEucmVzPWRhLnJlcywgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMuZGE9ZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlLmRpc2NvcmQ9bWVyZ2UuZGlzY29yZCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcmxhcD1vdmVybGFwLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICMgcmV0dXJucyBhIHZlY3RvciBncm91cCB2YWx1ZXMgZm9yIGVhY2ggbmhvb2QgLS0+CjwhLS0gfSAtLT4KCjwhLS0gbmhvb2QuZ3IgPC0gdW5pcXVlKG5ocy5kYS5ncikgLS0+Cgo8IS0tIG5hbWVzKG5ocy5kYS5ncikgLS0+CjwhLS0gIyBuYW1lcyhuaHMuZGEuZ3IpIDwtIG1hdGNoKG5hbWVzKG5ocy5kYS5nciksIG5ob29kSW5kZXgoeCkpIC0tPgo8IS0tIG5ocy5kYS5nci5hbGwgPC0gcmVwKE5BLCBsZW5ndGgobmhvb2RzKHgpKSkgLS0+Cgo8IS0tIG5ocy5kYS5nci5hbGxbYXMubnVtZXJpYyhuYW1lcyhuaHMuZGEuZ3IpKV0gPC0gbmhzLmRhLmdyIC0tPgoKCjwhLS0gIyBwZXJmb3JtIERHRSBfd2l0aGluXyBlYWNoIGdyb3VwIG9mIGNlbGxzIHVzaW5nIHRoZSBpbnB1dCBkZXNpZ24gbWF0cml4IC0tPgo8IS0tIG1lc3NhZ2UocGFzdGUwKCJOaG9vZHMgYWdncmVnYXRlZCBpbnRvICIsIGxlbmd0aChuaG9vZC5nciksICIgZ3JvdXBzIikpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGNlbGwybmhvb2RzIDwtIGZ1bmN0aW9uKHgpeyAtLT4KPCEtLSAgIG5ocyA8LSBsYXBwbHkobmhvb2RzKHgpLCBmdW5jdGlvbihuaCkgYXMudmVjdG9yKG5oKSkgLS0+CjwhLS0gICAjIG5ob29kX21hdCA8LSBtYXRyaXgobnJvdyA9IG5jb2woeCksIG5jb2w9bGVuZ3RoKG5ob29kcyh4KSkpIC0tPgo8IS0tICAgbmhvb2RfbWF0IDwtIHNhcHBseShuaHMsIGZ1bmN0aW9uKG5oKSBpZmVsc2UoMTpuY29sKHgpICVpbiUgbmgsIDEsIDApKSAtLT4KPCEtLSAgIHJldHVybihuaG9vZF9tYXQpIC0tPgo8IS0tIH0gLS0+CjwhLS0gYGBgIC0tPgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tIHggPC0gbGl2ZXJfbWlsbyAtLT4KPCEtLSBuaF9tYXQgPC0gY2VsbDJuaG9vZHMoeCkgLS0+CjwhLS0gZmFrZS5tZXRhIDwtIGRhdGEuZnJhbWUoIkNlbGxJRCI9Y29sbmFtZXMoeCkpIC0tPgo8IS0tICMgcm93bmFtZXMoZmFrZS5tZXRhKSA8LSBmYWtlLm1ldGEkQ2VsbElEIC0tPgo8IS0tIG5ocy5kYS5nci5hbGwgPC0gaWZlbHNlKGdyMSwgMSwgaWZlbHNlKGdyMiwgMiwgTkEpKSAtLT4KCjwhLS0gZGltKG5oX21hdCkgLS0+CjwhLS0gbmhvb2QuZ3IgPC0gdW5pcXVlKG5ob29kLmRhLmdyLmFsbFshaXMubmEobmhvb2QuZGEuZ3IuYWxsKV0pIC0tPgo8IS0tIGZvcihpIGluIHNlcV9hbG9uZyhuaG9vZC5ncikpeyAtLT4KPCEtLSAgIGdyLmNlbGxzIDwtIHJvd1N1bXMobmhfbWF0W3doaWNoKG5ocy5kYS5nci5hbGwgPT0gbmhvb2QuZ3JbaV0pLF0pID4gMCAtLT4KPCEtLSAgIGZha2UubWV0YVsscGFzdGUwKCJncm91cF8iLCBpKV0gPC0gZ3IuY2VsbHMgLS0+CjwhLS0gfSAtLT4KPCEtLSAjIGRpbShmYWtlLm1ldGFbcm93U3VtcyhuaF9tYXRbLHdoaWNoKG5ocy5kYS5nci5hbGwgPT0gbmhvb2QuZ3JbaV0pXSkgPiAwLF0pIC0tPgo8IS0tICMgIyBuaHMuZGEuZ3IuYWxsIDwtIGlmZWxzZSgxOmxlbmd0aChuaG9vZHMoeCkpICVpbiUgbWF0Y2gobmFtZXMobmhzLmRhLmdyKSwgbmhvb2RJbmRleCh4KSksIG5ocy5kYS5nciwgTkEpIC0tPgo8IS0tICMgZm9yKGkgaW4gc2VxX2Fsb25nKG5ob29kLmdyKSl7IC0tPgo8IS0tICMgICAgIG5ob29kLnggPC0gbmhzLmRhLmdyLmFsbCA9PSBuaG9vZC5ncltpXSAtLT4KPCEtLSAjICAgICBuaG9vZC54W2lzLm5hKG5ob29kLngpXSA8LSBGQUxTRSAtLT4KPCEtLSAjICAgICBmYWtlLm1ldGFbdW5saXN0KG5ob29kcyh4KVtkYS5yZXMkU3BhdGlhbEZEUiA8IGRhLmZkcl1bbmhvb2QueF0pLCBwYXN0ZTAoImdyb3VwXyIsIGkpXSA8LSBuaG9vZC5ncltpXSAtLT4KPCEtLSAjIH0gLS0+CgoKPCEtLSBmYWtlLm1ldGEgPC0gLS0+CjwhLS0gICBmYWtlLm1ldGEgJT4lIC0tPgo8IS0tICAgbXV0YXRlKE5ob29kLkdyb3VwID0gaWZlbHNlKGdyb3VwXzEsIDEsIGlmZWxzZShncm91cF8yLCAyLCBOQSkpKSAtLT4KPCEtLSByb3duYW1lcyhmYWtlLm1ldGEpIDwtIGZha2UubWV0YSRDZWxsSUQgLS0+Cgo8IS0tIGNvbERhdGEoZW5kb19taWxvKVtbImdyb3VwXzEiXV0gPC0gYXMuZmFjdG9yKGZha2UubWV0YVtjb2xuYW1lcyhlbmRvX21pbG8pLCJncm91cF8xIl0pIC0tPgo8IS0tIGNvbERhdGEoZW5kb19taWxvKVtbImdyb3VwXzIiXV0gPC0gYXMuZmFjdG9yKGZha2UubWV0YVtjb2xuYW1lcyhlbmRvX21pbG8pLCJncm91cF8yIl0pIC0tPgo8IS0tIGNvbERhdGEoZW5kb19taWxvKVtbIk5ob29kR3JvdXAiXV0gPC0gYXMuZmFjdG9yKGZha2UubWV0YVtjb2xuYW1lcyhlbmRvX21pbG8pLCJOaG9vZEdyb3VwIl0pIC0tPgo8IS0tIHBsb3RVTUFQKGVuZG9fbWlsbywgY29sb3VyX2J5PSJOaG9vZEdyb3VwIikgLS0+Cgo8IS0tIGBgYCAtLT4KCgoKPCEtLSBgYGB7cn0gLS0+Cgo8IS0tICMgb25seSBjb21wYXJlIGFnYWluc3QgdGhlIG90aGVyIERBIG5laWdoYm91cmhvb2RzIC0tPgo8IS0tIHggPC0geFssICFpcy5uYShmYWtlLm1ldGEkTmhvb2QuR3JvdXApXSAtLT4KPCEtLSBmYWtlLm1ldGEgPC0gZmFrZS5tZXRhWyFpcy5uYShmYWtlLm1ldGEkTmhvb2QuR3JvdXApLCBdIC0tPgoKPCEtLSBpZighaXMubnVsbChzdWJzZXQucm93KSl7IC0tPgo8IS0tICAgICB4IDwtIHhbc3Vic2V0LnJvdywgLCBkcm9wPUZBTFNFXSAtLT4KPCEtLSB9IC0tPgoKPCEtLSAgICAgZXhwcnMgPC0gYXNzYXkoeCwgYXNzYXkpIC0tPgoKPCEtLSAgICAgbWFya2VyLmxpc3QgPC0gbGlzdCgpIC0tPgo8IS0tICAgICBpLmNvbnRyYXN0IDwtIGMoIlRlc3RUZXN0IC0gVGVzdFJlZiIpICMgYWx3YXlzIHVzZSBjb250cmFzdHMgZm9yIHRoaXMgLS0+Cgo8IS0tICAgICAjIGlmIHRoZXJlIGlzIG9ubHkgMSBncm91cCwgdGhlbiBuZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbCBuZWlnaGJvdXJob29kcyAtLT4KPCEtLSAgICAgIyBhcmUgbm90IGluIHRoaXMgZ3JvdXAgLSBvdGhlcndpc2UgY2FuJ3QgZG8gYW55IERHRSB0ZXN0aW5nIC0tPgo8IS0tICAgICBpZihsZW5ndGgobmhvb2QuZ3IpID09IDEpeyAtLT4KPCEtLSAgICAgICAgIGlmKHN1bShmYWtlLm1ldGEkTmhvb2QuR3JvdXAgPT0gbmhvb2QuZ3JbMV0pID09IG5yb3coZmFrZS5tZXRhKSl7IC0tPgo8IS0tICAgICAgICAgICAgIHdhcm5pbmcoIkFsbCBncmFwaCBuZWlnaGJvdXJob29kcyBhcmUgaW4gdGhlIHNhbWUgZ3JvdXAgLSBjYW5ub3QgcGVyZm9ybSBER0UgdGVzdGluZy4gUmV0dXJuaW5nIE5VTEwiKSAtLT4KPCEtLSAgICAgICAgICAgICByZXR1cm4oTlVMTCkgLS0+CjwhLS0gICAgICAgICB9IC0tPgo8IS0tICAgICB9IC0tPgoKPCEtLSAgICAgZm9yKGkgaW4gc2VxX2Fsb25nKG5ob29kLmdyKSl7IC0tPgo8IS0tICAgICAgICAgaS5tZXRhIDwtIGZha2UubWV0YSAtLT4KPCEtLSAgICAgICAgIGkubWV0YSRUZXN0IDwtICJSZWYiIC0tPgo8IS0tICAgICAgICAgaS5tZXRhJFRlc3RbZmFrZS5tZXRhJE5ob29kLkdyb3VwID09IG5ob29kLmdyW2ldXSA8LSAiVGVzdCIgLS0+Cgo8IS0tICAgICAgICAgaWYobmNvbChleHBycykgPiAxICYgbnJvdyhpLm1ldGEpID4gMSl7IC0tPgo8IS0tICAgICAgICAgICAgIGkuZGVzaWduIDwtIGFzLmZvcm11bGEoIiB+IDAgKyBUZXN0IikgLS0+CjwhLS0gICAgICAgICAgICAgaS5tb2RlbCA8LSBtb2RlbC5tYXRyaXgoaS5kZXNpZ24sIGRhdGE9aS5tZXRhKSAtLT4KPCEtLSAgICAgICAgICAgICByb3duYW1lcyhpLm1vZGVsKSA8LSByb3duYW1lcyhpLm1ldGEpIC0tPgo8IS0tICAgICAgICAgfSAtLT4KCjwhLS0gICAgICAgICBzaW5rKGZpbGU9Ii9kZXYvbnVsbCIpIC0tPgo8IS0tICAgICAgICAgZ2MoKSAtLT4KPCEtLSAgICAgICAgIHNpbmsoZmlsZT1OVUxMKSAtLT4KCjwhLS0gICAgICAgICBpZihhc3NheSA9PSAibG9nY291bnRzIil7IC0tPgo8IS0tICAgICAgICAgICAgIGkucmVzIDwtIC5wZXJmb3JtX2xvZ25vcm1hbF9kZ2UoZXhwcnMsIGkubW9kZWwsIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmUub2Zmc2V0PWdlbmUub2Zmc2V0KSAtLT4KPCEtLSAgICAgICAgIH0gZWxzZSBpZihhc3NheSA9PSAiY291bnRzIil7IC0tPgo8IS0tICAgICAgICAgICAgIGkucmVzIDwtIC5wZXJmb3JtX2NvdW50c19kZ2UoZXhwcnMsIGkubW9kZWwsIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmUub2Zmc2V0PWdlbmUub2Zmc2V0KSAtLT4KPCEtLSAgICAgICAgIH0gZWxzZXsgLS0+CjwhLS0gICAgICAgICAgICAgd2FybmluZygiQXNzYXkgdHlwZSBpcyBub3QgY291bnRzIG9yIGxvZ2NvdW50cyAtIGFzc3VtaW5nIChsb2cpLW5vcm1hbCBkaXN0cmlidXRpb24uIFVzZSB0aGVzZSByZXN1bHRzIGF0IHlvdXIgcGVyaWwiKSAtLT4KPCEtLSAgICAgICAgICAgICBpLnJlcyA8LSAucGVyZm9ybV9sb2dub3JtYWxfZGdlKGV4cHJzLCBpLm1vZGVsLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmUub2Zmc2V0PWdlbmUub2Zmc2V0KSAtLT4KPCEtLSAgICAgICAgIH0gLS0+Cgo8IS0tICAgICAgICAgaS5yZXMkYWRqLlAuVmFsW2lzLm5hKGkucmVzJGFkai5QLlZhbCldIDwtIDEgLS0+CjwhLS0gICAgICAgICBpLnJlcyRsb2dGQ1tpcy5pbmZpbml0ZShpLnJlcyRsb2dGQyldIDwtIDAgLS0+Cgo8IS0tICAgICAgICAgaS5yZXMgPC0gaS5yZXNbLCBjKCJsb2dGQyIsICJhZGouUC5WYWwiKV0gLS0+CjwhLS0gICAgICAgICBjb2xuYW1lcyhpLnJlcykgPC0gcGFzdGUoY29sbmFtZXMoaS5yZXMpLCBuaG9vZC5ncltpXSwgc2VwPSJfIikgLS0+CjwhLS0gICAgICAgICBtYXJrZXIubGlzdFtbcGFzdGUwKG5ob29kLmdyW2ldKV1dIDwtIGkucmVzIC0tPgo8IS0tICAgICB9IC0tPgoKPCEtLSAgICAgbWFya2VyLmRmIDwtIGRvLmNhbGwoY2JpbmQuZGF0YS5mcmFtZSwgbWFya2VyLmxpc3QpIC0tPgo8IS0tICAgICBjb2xuYW1lcyhtYXJrZXIuZGYpIDwtIGdzdWIoY29sbmFtZXMobWFya2VyLmRmKSwgcGF0dGVybj0iXlswLTldK1xcLiIsIHJlcGxhY2VtZW50PSIiKSAtLT4KPCEtLSAgICAgbWFya2VyLmRmJEdlbmVJRCA8LSByb3duYW1lcyhpLnJlcykgLS0+Cgo8IS0tICAgICBpZihpc1RSVUUocmV0dXJuLmdyb3VwcykpeyAtLT4KPCEtLSAgICAgICAgIG91dC5saXN0IDwtIGxpc3QoImdyb3VwcyI9ZmFrZS5tZXRhLCAiZGdlIj1tYXJrZXIuZGYpIC0tPgo8IS0tICAgICAgICAgcmV0dXJuKG91dC5saXN0KSAtLT4KPCEtLSAgICAgfWVsc2V7IC0tPgo8IS0tICAgICAgICAgcmV0dXJuKG1hcmtlci5kZikgLS0+CjwhLS0gICAgIH0gLS0+CjwhLS0gbmhvb2RfbWFya2VycyA8LSBvdXQubGlzdCAtLT4KPCEtLSBzdW0obWFya2VyLmRmJGFkai5QLlZhbF8xIDwgMC4wMDEpIC0tPgoKPCEtLSBiY2VsbF9nZW5lcyA8LSBjKCdNUzRBMScsICJDRDE5IiwgIkZDR1IyQiIsICJJR0hBMSIpIC0tPgoKPCEtLSBwbG90VU1BUChlbmRvX21pbG8sIGNvbG91cl9ieT1iY2VsbF9nZW5lc1szXSkgLS0+Cgo8IS0tIGBgYCAtLT4KCiMjIyMgVmlzdWFsaXplIGFzIHZvbGNhbm8gCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1hcmtlci5kZiAlPiUKICAgbXV0YXRlKGFkai5QLlZhbF8xID0gaWZlbHNlKC0gbG9nMTAoYWRqLlAuVmFsXzEpID4gMzAwLCAxZS0zMDAsIGFkai5QLlZhbF8xKSkgJT4lCiAgbXV0YXRlKGxhYmVsPWlmZWxzZSgoYWRqLlAuVmFsXzEpIDwgMC4wNSwgR2VuZUlELCBOQSkpICU+JQogIGdncGxvdChhZXMobG9nRkNfMiwgLWxvZzEwKGFkai5QLlZhbF8xKSwgCiAgICAgICAgICAgICAjIGNvbG9yPWhpZ2hsaWdodAogICAgICAgICAgICAgKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMobGFiZWw9bGFiZWwpKSArCiAgeGxhYigibG9nRkMiKSArIHlsYWIoIi0gbG9nMTAoQWRqLiBQIHZhbHVlKSIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMikKICAKICAKYGBgCgojIyMjIFZpc3VhbGl6ZSBhcyBoZWF0bWFwIAooZ2VuZSBleHByZXNzaW9uIHZhbHVlcyBhcmUgc2NhbGVkIGJldHdlZW4gMCBhbmQgMSBmb3IgZWFjaCBnZW5lKQoKYGBge3IsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptYXJrZXJfZ2VuZXMgPC0gbWFya2VyLmRmICU+JQogIGRwbHlyOjpmaWx0ZXIoYWRqLlAuVmFsXzEgPCAwLjA1KSAlPiUKICBwdWxsKEdlbmVJRCkKCmhpZ2hsaWdodF9nZW5lcyA8LSBjKCJQTFZBUCIsICJTT1gxNCIsICJWV0ExIiwgIkFDS1IxIiwgIklMMzIiLAogICAgICAgICAgICAgICAgICAgICAiQ0xFQzRHIiwgIkNMRUM0TSIsICJTVEFCMiIsICJNUkMxIiwgIkxZVkUxIiwKICAgICAgICAgICAgICAgICAgICAgIkNEMTQiLCAiU09YMTciLCAiV05UMiIsICJSU1BPMyIsICJBSUYxTCIsCiAgICAgICAgICAgICAgICAgICAgICJQUk9YMSIsICJQRFBOIiwiQ1BFIiwgIkNEMzIwIiwgIkJNUEVSIikKCmZpZzRfYmJyaWdodCA8LSBwbG90Tmhvb2RFeHByZXNzaW9uREEobGl2ZXJfbWlsbywgbWlsb19yZXMsIG1hcmtlcl9nZW5lcywgY2x1c3Rlcl9mZWF0dXJlcyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjEsCiAgICAgICAgICAgICAgICAgICAgICBzY2FsZV90b18xID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIHN1YnNldC5uaG9vZHMgPSBtaWxvX3JlcyRhbm5vdGF0aW9uX2xpbmVhZ2U9PSJFbmRvdGhlbGlhIiwKICAgICAgICAgICAgICAgICAgICAgIGhpZ2hsaWdodF9mZWF0dXJlcyA9IGhpZ2hsaWdodF9nZW5lcywgc2hvd19yb3duYW1lcyA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICkgKwogIHlsYWIoIkRFIGdlbmVzIikgKwogICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTIyKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjQpKSArCiAgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMSwxMCkpCgpmaWc0X2JicmlnaHQKYGBgCgo8IS0tIEN1c3RvbWl6ZSBwbG90dGluZyBmb3IgcGFwZXIgZmlndXJlIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0geCA8LSBsaXZlcl9taWxvIC0tPgo8IS0tIGRhLnJlcyA8LSBtaWxvX3JlcyAtLT4KCjwhLS0gY2x1c3Rlcl9mZWF0dXJlcyA9IFRSVUUgLS0+CjwhLS0gYWxwaGEgPSAwLjEgLS0+CjwhLS0gc2NhbGVfdG9fMSA9IFRSVUUgLS0+CjwhLS0gc3Vic2V0Lm5ob29kcyA9IG1pbG9fcmVzJGFubm90YXRpb25fbGluZWFnZT09IkVuZG90aGVsaWEiIC0tPgo8IS0tIGZlYXR1cmVzIDwtIG1hcmtlcl9nZW5lcyAtLT4KCjwhLS0gZXhwcl9tYXQgPC0gbmhvb2RFeHByZXNzaW9uKHgpW2ZlYXR1cmVzLF0gLS0+CjwhLS0gY29sbmFtZXMoZXhwcl9tYXQpIDwtIDE6bGVuZ3RoKG5ob29kcyh4KSkgLS0+Cgo8IS0tICMjIEdldCBuaG9vZCBleHByZXNzaW9uIG1hdHJpeCAtLT4KPCEtLSBpZiAoIWlzLm51bGwoc3Vic2V0Lm5ob29kcykpIHsgLS0+CjwhLS0gICBleHByX21hdCA8LSBleHByX21hdFssc3Vic2V0Lm5ob29kcywgZHJvcD1GQUxTRV0gLS0+CjwhLS0gfSAtLT4KCjwhLS0gaWYgKCFpc0ZBTFNFKHNjYWxlX3RvXzEpKSB7IC0tPgo8IS0tICAgZXhwcl9tYXQgPC0gdChhcHBseShleHByX21hdCwgMSwgZnVuY3Rpb24oeCkgKHggLSBtaW4oeCkpLyhtYXgoeCktIG1pbih4KSkpKSAtLT4KPCEtLSB9IC0tPgoKPCEtLSByb3duYW1lcyhleHByX21hdCkgPC0gc3ViKHBhdHRlcm4gPSAiLSIsIHJlcGxhY2VtZW50ID0gIi4iLCByb3duYW1lcyhleHByX21hdCkpICMjIFRvIGF2b2lkIHByb2JsZW1zIHdoZW4gY29udmVydGluZyB0byBkYXRhLmZyYW1lIC0tPgoKPCEtLSBwbF9kZiA8LSBkYXRhLmZyYW1lKHQoZXhwcl9tYXQpKSAlPiUgLS0+CjwhLS0gICByb3duYW1lc190b19jb2x1bW4oIk5ob29kIikgJT4lIC0tPgo8IS0tICAgbXV0YXRlKE5ob29kPWFzLmRvdWJsZShOaG9vZCkpICU+JSAtLT4KPCEtLSAgIGxlZnRfam9pbihkYS5yZXMsIGJ5PSJOaG9vZCIpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShsb2dGQ19yYW5rPXBlcmNlbnRfcmFuayhsb2dGQykpIC0tPgoKPCEtLSAjIyBUb3AgcGxvdDogbmhvb2RzIHJhbmtlZCBieSBEQSBsb2cgRkMgLS0+CjwhLS0gcGxfdG9wIDwtIHBsX2RmICU+JSAtLT4KPCEtLSAgIG11dGF0ZShpc19zaWduaWYgPSBpZmVsc2UoU3BhdGlhbEZEUiA8IGFscGhhLCBwYXN0ZTAoIlNwYXRpYWxGRFIgPCAiLCBhbHBoYSksIE5BKSkgJT4lIC0tPgo8IS0tICAgZ2dwbG90KGFlcyhsb2dGQ19yYW5rLCBsb2dGQykpICsgLS0+CjwhLS0gICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0yKSArIC0tPgo8IS0tICAgZ2VvbV9wb2ludChzaXplPTAuMiwgY29sb3I9ImdyZXkiKSArIC0tPgo8IS0tICAgZ2VvbV9wb2ludChkYXRhPS4gJT4lIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGlzX3NpZ25pZikpLCBhZXMoY29sb3I9aXNfc2lnbmlmKSwgc2l6ZT0xKSArIC0tPgo8IS0tICAgdGhlbWVfYncoYmFzZV9zaXplPTIyKSArIC0tPgo8IS0tICAgeWxhYigiREEgbG9nRkMiKSArIC0tPgo8IS0tICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0icmVkIiwgbmFtZT0iIikgKyAtLT4KPCEtLSAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTIpKSkgKyAtLT4KPCEtLSAgIHNjYWxlX3hfY29udGludW91cyhleHBhbmQgPSBjKDAuMDEsIDApKSArIC0tPgo8IS0tICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSAtLT4KCjwhLS0gIyMgQm90dG9tIHBsb3Q6IGdlbmUgZXhwcmVzc2lvbiBoZWF0bWFwIC0tPgo8IS0tIGlmIChpc1RSVUUoY2x1c3Rlcl9mZWF0dXJlcykpIHsgLS0+CjwhLS0gICByb3cub3JkZXIgPC0gaGNsdXN0KGRpc3QoZXhwcl9tYXQpKSRvcmRlciAjIGNsdXN0ZXJpbmcgLS0+CjwhLS0gICBvcmRlcmVkX2ZlYXR1cmVzIDwtIHJvd25hbWVzKGV4cHJfbWF0KVtyb3cub3JkZXJdIC0tPgo8IS0tIH0gZWxzZSB7IC0tPgo8IS0tICAgb3JkZXJlZF9mZWF0dXJlcyA8LSByb3duYW1lcyhleHByX21hdCkgLS0+CjwhLS0gfSAtLT4KCgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTB9IC0tPgo8IS0tICMgZGV0YWNoKCdwYWNrYWdlOkVuc0RiLkhzYXBpZW5zLnY4NicpIC0tPgo8IS0tICMgZGV0YWNoKCdwYWNrYWdlOmVuc2VtYmxkYicpIC0tPgoKPCEtLSBoaWdobGlnaHRfZ2VuZXMgPC0gYygiUExWQVAiLCAiU09YMTQiLCAiVldBMSIsICJBQ0tSMSIsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICJDTEVDNEciLCAiQ0xFQzRNIiwgIlNUQUIyIiwgIk1SQzEiLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAiQ0QxNCIsICJDQ0wyMSIsICJTT1gxNyIsICJXTlQyIiwgIlJTUE8zIiwgIkFJRjFMIiwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgIlBST1gxIiwgIlBEUE4iLCJDUEUiLCAiQ0QzMjAiKSAtLT4KCjwhLS0gcGxfYm90dG9tIDwtIHBsX2RmICU+JSAtLT4KPCEtLSAgIHBpdm90X2xvbmdlcihjb2xzPXJvd25hbWVzKGV4cHJfbWF0KSwgbmFtZXNfdG89J2ZlYXR1cmUnLCB2YWx1ZXNfdG89ImF2Z19leHByIikgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGZlYXR1cmU9ZmFjdG9yKGZlYXR1cmUsIGxldmVscz1vcmRlcmVkX2ZlYXR1cmVzKSkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGxhYmVsPWlmZWxzZShmZWF0dXJlICVpbiUgaGlnaGxpZ2h0X2dlbmVzLCBhcy5jaGFyYWN0ZXIoZmVhdHVyZSksIE5BKSkgJT4lIC0tPgo8IS0tICAgZ2dwbG90KGFlcyhsb2dGQ19yYW5rLCBmZWF0dXJlLCBmaWxsPWF2Z19leHByKSkgKyAtLT4KPCEtLSAgIGdlb21fdGlsZSgpICsgLS0+CjwhLS0gICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb249Im1hZ21hIiwgbmFtZT0iU2NhbGVkIFxuZXhwcmVzc2lvbiIpICsgLS0+CjwhLS0gICB4bGFiKCJFbmRvdGhlbGlhbCBOZWlnaGJvdXJob29kcyIpICsgeWxhYigiREUgZ2VuZXMiKSArIC0tPgo8IS0tICAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMC4wMSwgMCksIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICMgbGltaXRzID0gYygwLCBtYXgocGxfZGYkbG9nRkNfcmFuaykgKyAwLjIpIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICkgKyAtLT4KPCEtLSAgIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kID0gYygwLjA0LDApKSArIC0tPgo8IS0tICAgY29vcmRfY2FydGVzaWFuKGNsaXA9Im9mZiIpICsgLS0+CjwhLS0gICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YT0uICU+JSBkcGx5cjo6ZmlsdGVyKCFpcy5uYShsYWJlbCkpICU+JSAtLT4KPCEtLSAgICAgICAgICAgICAgIGdyb3VwX2J5KGxhYmVsKSAlPiUgLS0+CjwhLS0gICAgICAgICAgICAgICBzdW1tYXJpc2UobG9nRkNfcmFuaz1tYXgobG9nRkNfcmFuayksIGF2Z19leHByPW1lYW4oYXZnX2V4cHIpLCBmZWF0dXJlPWRwbHlyOjpmaXJzdChmZWF0dXJlKSksIC0tPgo8IS0tICAgICAgICAgICAgIGFlcyhsYWJlbD1sYWJlbCwgeD1sb2dGQ19yYW5rKSwgc2l6ZT02LCAgLS0+CjwhLS0gICAgICAgICAgICAgeGxpbSA9IGMobWF4KHBsX2RmJGxvZ0ZDX3JhbmspICsgMC4wNSwgbWF4KHBsX2RmJGxvZ0ZDX3JhbmspICsgMC4xNSksIC0tPgo8IS0tICAgICAgICAgICAgICMgeWxpbSA9IGMobWluKHBsX2RmJCkpIC0tPgo8IS0tICAgICAgICAgICAgIGhqdXN0PTEsIC0tPgo8IS0tICAgICAgICAgICAgIHNlZ21lbnQuY3VydmF0dXJlID0gLTAuMSwgLS0+CjwhLS0gICAgIHNlZ21lbnQubmNwID0gMywgLS0+CjwhLS0gICAgIHNlZ21lbnQuYW5nbGUgPSAyMCwgLS0+CjwhLS0gICAgICAgICAgICAgbWluLnNlZ21lbnQubGVuZ3RoID0gMCwgc2VlZD00MiAtLT4KPCEtLSAgICAgICAgICAgICApICsgLS0+CjwhLS0gICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIyKSArIC0tPgo8IS0tICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZS54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIC0tPgo8IS0tICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksIC0tPgo8IS0tICAgICAgICAgcGFuZWwuc3BhY2luZyA9IG1hcmdpbigyLCAyLCAyLCAyLCAiY20iKSwgLS0+CjwhLS0gICAgICAgICBsZWdlbmQubWFyZ2luPW1hcmdpbigwLDAsMCwwKSwgLS0+CjwhLS0gICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbj1tYXJnaW4oMTAsMTAsMTAsMTApIC0tPgo8IS0tICAgICAgICAgKSAtLT4KCjwhLS0gIyMgQXNzZW1ibGUgcGxvdCAtLT4KPCEtLSBmaWc0X2JicmlnaHQgPC0gIChwbF90b3AgLyBwbF9ib3R0b20pICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMSw0KSwgZ3VpZGVzID0gImNvbGxlY3QiKSAmICAtLT4KPCEtLSAgICAgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb249YygwLCAxKSkgLS0+CjwhLS0gZmlnNF9iYnJpZ2h0ICsgIGdnc2F2ZSgifi9taWxvX291dHB1dC9saXZlcl9ERUdfaGVhdG1hcC5wZGYiLCB3aWR0aD05LCBoZWlnaHQgPSA5KSAtLT4KCjwhLS0gYGBgIC0tPgoKIyMjIEdPIHRlcm0gYW5hbHlzaXMKCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCdjbHVzdGVyUHJvZmlsZXInKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCdtc2lnZGJyJykKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkobXNpZ2RicikKCm1fZGYgPC0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIpCm1fdDJnIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDNSIsIHN1YmNhdGVnb3J5ID0gIkJQIikgICU+JSAKICBkcGx5cjo6c2VsZWN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKQoKbWFya2VyX2dlbmVzX3VwIDwtIG1hcmtlci5kZiAlPiUKICBkcGx5cjo6ZmlsdGVyKGFkai5QLlZhbF8xIDwgMC4wNSAmIGxvZ0ZDXzEgPiAwKSAlPiUKICBwdWxsKEdlbmVJRCkKCm1hcmtlcl9nZW5lc19kb3duIDwtIG1hcmtlci5kZiAlPiUKICBkcGx5cjo6ZmlsdGVyKGFkai5QLlZhbF8xIDwgMC4wNSAmIGxvZ0ZDXzEgPCAwKSAlPiUKICBwdWxsKEdlbmVJRCkKCmVtX3VwIDwtIGVucmljaGVyKG1hcmtlcl9nZW5lc191cCwgVEVSTTJHRU5FPW1fdDJnLCBwQWRqdXN0TWV0aG9kID0gImZkciIsIAogICAgICAgICAgICAgICAgICB1bml2ZXJzZSA9IHJvd25hbWVzKGxpdmVyX21pbG8pCiAgICAgICAgICAgICAgICAgICkKZW1fZG93biA8LSBlbnJpY2hlcihtYXJrZXJfZ2VuZXNfZG93biwgVEVSTTJHRU5FPW1fdDJnLCBwQWRqdXN0TWV0aG9kID0gImZkciIsIAogICAgICAgICAgICAgICAgICAgIHVuaXZlcnNlID0gcm93bmFtZXMobGl2ZXJfbWlsbykKICAgICAgICAgICAgICAgICAgICApCgplbV9yZXNfdXAgPC0gZW1fdXBAcmVzdWx0W2VtX3VwQHJlc3VsdCRxdmFsdWUgPCAwLjEsXSAlPiUKICBkcGx5cjo6c2VsZWN0KC0gYyhEZXNjcmlwdGlvbikpCmVtX3Jlc19kb3duIDwtIGVtX2Rvd25AcmVzdWx0W2VtX2Rvd25AcmVzdWx0JHF2YWx1ZSA8IDAuMSxdICU+JQogIGRwbHlyOjpzZWxlY3QoLSBjKERlc2NyaXB0aW9uKSkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmVtX3Jlc191cCAlPiUKICB0b3BfbigyMCwgLWxvZzEwKHF2YWx1ZSkpICU+JQogIG11dGF0ZShUZXJtPWZhY3RvcihJRCwgbGV2ZWxzPXJldih1bmlxdWUoSUQpKSkpICU+JQogIGdncGxvdChhZXMoVGVybSwgLWxvZzEwKHF2YWx1ZSkpKSArCiAgZ2VvbV9wb2ludCgpICsKICBjb29yZF9mbGlwKCkgKwogIHhsYWIoIkdPIEJpb2xvZ2ljYWwgRnVuY3Rpb24iKSArIHlsYWIoIi1sb2cxMChBZGouIHAtdmFsdWUpIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0xNCkgKwogIGdndGl0bGUoIk1hcmtlcnMgb2YgY2lycmhvdGljIikKCmVtX3Jlc19kb3duICU+JQogIHRvcF9uKDMwLCAtbG9nMTAocXZhbHVlKSkgJT4lCiAgbXV0YXRlKFRlcm09ZmFjdG9yKElELCBsZXZlbHM9cmV2KHVuaXF1ZShJRCkpKSkgJT4lCiAgZ2dwbG90KGFlcyhUZXJtLCAtbG9nMTAocXZhbHVlKSkpICsKICBnZW9tX3BvaW50KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgeGxhYigiR08gQmlvbG9naWNhbCBGdW5jdGlvbiIpICsgeWxhYigiLWxvZzEwKEFkai4gcC12YWx1ZSkiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplPTE0KSArCiAgZ2d0aXRsZSgiTWFya2VycyBvZiBoZWFsdGh5IikKYGBgCgojIyMgRnVsbCBHTyBlbnJpY2htZW50IC0gdXAgaW4gY2lycmhvdGljCihgZ2VuZUlEYCBjb2x1bW4gaW5kaWNhdGVzIHdoaWNoIGdlbmVzIGJlbG9uZyB0byBnZW5lIG9udG9sb2d5KQpgYGB7cn0KZW1fcmVzX3VwCmBgYAoKIyMjIEZ1bGwgR08gZW5yaWNobWVudCAtIHVwIGluIGhlYWx0eQooYGdlbmVJRGAgY29sdW1uIGluZGljYXRlcyB3aGljaCBnZW5lcyBiZWxvbmcgdG8gZ2VuZSBvbnRvbG9neSkKYGBge3J9CmVtX3Jlc19kb3duCmBgYAoKCiMjIENsb3NlLXVwIG9uIENob2xhbmdpb2N5dGVzCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBjaG9sX21pbG8gPC0gc2NhdGVyOjpydW5VTUFQKGxpdmVyX21pbG9bLGxpdmVyX21pbG8kYW5ub3RhdGlvbl9saW5lYWdlPT0iQ2hvbGFuZ2lvY3l0ZXMiXSwgIGRpbXJlZD0nUENBJykgLS0+CjwhLS0gcGxvdFVNQVAoY2hvbF9taWxvLCBjb2xvdXJfYnkgPSAiYW5ub3RhdGlvbl9pbmRlcHRoIikgLS0+CjwhLS0gYGBgIC0tPgoKRmlsdGVyIG91dCBjZWxscyB0aGF0IHNob3cgY29udGFtaW5hdGlvbiBmcm9tIGltbXVuZSBjZWxscyAoZXhwcmVzc2lvbiBvZiBpbW11bmUgbWFya2VycykKCmBgYHtyfQprZWVwIDwtIGxvZ2NvdW50cyhjaG9sX21pbG8pWyJDRDE5IixdID09IDAgfCBsb2djb3VudHMoY2hvbF9taWxvKVsiTVM0QTEiLF0gPT0gMApjaG9sX21pbG8gPC0gY2hvbF9taWxvWyxrZWVwXQpjaG9sX21pbG8gPC0gc2NhdGVyOjpydW5VTUFQKGNob2xfbWlsbywgIGRpbXJlZD0nUENBJykKCnBsb3RVTUFQKGNob2xfbWlsbywgY29sb3VyX2J5ID0gImFubm90YXRpb25faW5kZXB0aCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQp1bWFwX2RmIDwtIGRhdGEuZnJhbWUocmVkdWNlZERpbShjaG9sX21pbG8sICJVTUFQIikpCmNvbG5hbWVzKHVtYXBfZGYpIDwtIGMoIlVNQVBfMSIsICJVTUFQXzIiKQoKY2hvbF91bWFwIDwtIGNiaW5kKHVtYXBfZGYsIGNvbmRpdGlvbj1jaG9sX21pbG8kY29uZGl0aW9uKSAlPiUKICAgZ2dwbG90KGFlcyhVTUFQXzEsIFVNQVBfMiwgY29sb3I9Y29uZGl0aW9uKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjMsIGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIiwgbmFtZT0nJykgKwogIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICBjb29yZF9maXhlZCgpICsKICBndWlkZXMoY29sb3I9Im5vbmUiKSArCiAgZmFjZXRfd3JhcChjb25kaXRpb25+LiwgbmNvbD0xKSArCiAgdGhlbWVfbm90aGluZygpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbj1jKDAuOSwwLjkpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9TkEpLCBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjIpKQoKY2hvbF91bWFwCmBgYAoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTQsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpdmVyX21pbG8yIDwtIGxpdmVyX21pbG8Kc3Vic2V0Lm5ob29kcyA8LSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkNob2xhbmdpbyIpCnJlZHVjZWREaW0obGl2ZXJfbWlsbzIsICJVTUFQIilbY29sbmFtZXMoY2hvbF9taWxvKSxdIDwtIHJlZHVjZWREaW0oY2hvbF9taWxvLCAiVU1BUCIpIAoKY2hvbF9nciA8LQogIHBsb3ROaG9vZEdyYXBoREEoCiAgbGl2ZXJfbWlsbzIsIG1pbG9fcmVzLAogIHN1YnNldC5uaG9vZHMgPSBzdWJzZXQubmhvb2RzLCAKICAjICkgPSlbMToobGVuZ3RoKCktMSldLCAKICBhbHBoYSA9IDAuMQogICkgICsKICAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0yMiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTI0KSkKICAKKGNob2xfdW1hcCArIGNob2xfZ3IgKSArIAogIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICBndWlkZXMgPSAiY29sbGVjdCIKICAgICAgICAgICAgICAgICkKIyBmaWc0X2JyaWdodDEgKwojICAgZ2dzYXZlKCJ+L21pbG9fb3V0cHV0L2xpdmVyX2VuZG9HcmFwaC5wZGYiLCB3aWR0aD05LCBoZWlnaHQgPSA1KSAgCgpgYGAKCiMjIyBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIERBIG5laWdoYm91cmhvb2RzCgpXZSBtZXJnZSBvdmVybGFwcGluZyBuaG9vZHMgd2l0aCBzaWduaWZpY2FudCBEQSBhbmQgdGhlIHNhbWUgZGlyZWN0aW9uIG9mIGxvZ0ZDLCBhbmQgdGhlbiB0ZXN0IGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIGNlbGxzIGluIGRpc2Vhc2Utc3BlY2lmaWMgYW5kIGhlYWx0aHktc3BlY2lmaWMgbmhvb2RzLiBUaGlzIGFsbG93cyB1cyB0byBwZXJmb3JtIGEgY29tcGFyaXNvbiB3aXRob3V0IGZ1cnRoZXIgY2x1c3RlcmluZy4KCjwhLS0gZHMgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tICMgZGVjX2xpdmVyIDwtIG1vZGVsR2VuZVZhcihsaXZlcl9taWxvKSAtLT4KPCEtLSAjIGZpdF9saXZlciA8LSBtZXRhZGF0YShkZWNfbGl2ZXIpIC0tPgo8IS0tICMgaHZncyA8LSBnZXRUb3BIVkdzKGRlY19saXZlciwgbj0zMDAwKSAtLT4KPCEtLSAjICAtLT4KPCEtLSAjICMjIGtlZXAgSFYgZ2VuZXMgZXhwcmVzc2VkIGluIGF0IGxlYXN0IDUlIG9mIGVuZG90aGVsaWFsIGNlbGxzIC0tPgo8IS0tICMgZW5kb19odmdfY250cyA8LSBjb3VudHMobGl2ZXJfbWlsbylbaHZncyxsaXZlcl9taWxvJGFubm90YXRpb25fbGluZWFnZT09IkVuZG90aGVsaWEiXSAtLT4KPCEtLSAjIGVuZG9faHZncyA8LSBodmdzWyhyb3dTdW1zKGVuZG9faHZnX2NudHMhPTApID4gKG5jb2woZW5kb19odmdfY250cykvMTAwKSo1KSAmIC0tPgo8IS0tICMgICAgICAgICAgICAgICAgICAgIChyb3dTdW1zKGVuZG9faHZnX2NudHMhPTApIDwgKG5jb2woZW5kb19odmdfY250cykvMTAwKSo3MCldIC0tPgo8IS0tICMgIyAmIC0tPgo8IS0tICMgIyAgICAgICAgICAgICAgICAgICAgIHJvd01lYW5zKGVuZG9faHZnX2NudHMpIDwgNV0gICMjIFJlbW92ZSB2ZXJ5IGhpZ2hseSBleHByZXNzZWQgLS0+CjwhLS0gIyAgLS0+CjwhLS0gIyBlbmRvX2h2Z3MgPC0gc2Nhbigifi9lbmRvX2h2Z3MudHh0Iiwgd2hhdCA9ICIiKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSAjIGxpdmVyX21pbG8gPC0gY2FsY05ob29kRXhwcmVzc2lvbihsaXZlcl9taWxvLCBzdWJzZXQucm93ID0gaHZncykgLS0+Cgo8IS0tIG5ob29kX21hcmtlcnMgPC0gZmluZE5ob29kTWFya2VycyhsaXZlcl9taWxvLCBtaWxvX3Jlcywgb3ZlcmxhcD0xLCByZXR1cm4uZ3JvdXBzID0gVFJVRSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNldC5yb3cgPSBodmdzLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGZjLnRocmVzaG9sZCA9IDAuMSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNldC5uaG9vZHMgPSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkVuZG8iKSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXB1dGUubmV3ID0gRkFMU0UpIC0tPgoKCjwhLS0gc3VtKG5ob29kX21hcmtlcnMkZGdlJGFkai5QLlZhbF8xIDwgMC4wNSkgLS0+CjwhLS0gbmhvb2RfbWFya2VycyRkZ2Vbbmhvb2RfbWFya2VycyRkZ2UkR2VuZUlEICVpbiUgaGlnaGxpZ2h0X2dlbmVzLF0gLS0+CjwhLS0gYGBgIC0tPgoKSGVyZSB3ZSBmaW5kIG1hcmtlcnMgZ3JvdXBpbmcgZ2VuZSBleHByZXNzaW9uIGNvdW50cyBieSBzYW1wbGVzIChpLmUuIHdlIGRvbid0IHRyZWF0IGNlbGxzIGFzIHJlcGxpY2F0ZXMsIGJ1dCBleHBsb2l0IHRoZSByZXBsaWNhdGlvbiBzdHJ1Y3R1cmUgdXNlZCBhbHNvIGZvciBEQSB0ZXN0aW5nKQoKYGBge3IsIGVjaG89RkFMU0V9CnggPSBsaXZlcl9taWxvCmRhLnJlcyA9IG1pbG9fcmVzCmRhLmZkcj0wLjEKYXNzYXk9ImNvdW50cyIKb3ZlcmxhcD0xCmxmYy50aHJlc2hvbGQgPSAwLjEKbWVyZ2UuZGlzY29yZD1GQUxTRQpzdWJzZXQucm93ID0gaHZncwpnZW5lLm9mZnNldD1GQUxTRQpyZXR1cm4uZ3JvdXBzPUZBTFNFCnN1YnNldC5uaG9vZHMgPSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkNob2wiKQpuYS5mdW5jdGlvbj0ibmEucGFzcyIKY29tcHV0ZS5uZXc9RkFMU0UKYml0cz1GQUxTRQphZ2dyZWdhdGUuc2FtcGxlcz1UUlVFCgoKaWYoaXMubnVsbChuYS5mdW5jdGlvbikpewogICAgd2FybmluZygiTlVMTCBwYXNzZWQgdG8gbmEuZnVuY3Rpb24sIHVzaW5nIG5hLnBhc3MiKQogICAgbmEuZnVuYyA8LSBnZXQoIm5hLnBhc3MiKQp9IGVsc2V7CiAgICB0cnlDYXRjaCh7CiAgICAgICAgbmEuZnVuYyA8LSBnZXQobmEuZnVuY3Rpb24pCiAgICB9LCB3YXJuaW5nPWZ1bmN0aW9uKHdhcm4pewogICAgICAgIHdhcm5pbmcod2FybikKICAgIH0sIGVycm9yPWZ1bmN0aW9uKGVycil7CiAgICAgICAgc3RvcChwYXN0ZTAoIk5BIGZ1bmN0aW9uICIsIG5hLmZ1bmN0aW9uLCAiIG5vdCByZWNvZ25pc2VkIikpCiAgICB9LCBmaW5hbGx5PXsKICAgIH0pCn0KCm4uZGEgPC0gc3VtKG5hLmZ1bmMoZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIpKQoKaWYoKG5jb2wobmhvb2RBZGphY2VuY3koeCkpID09IGxlbmd0aChuaG9vZHMoeCkpKSAmIGlzRkFMU0UoY29tcHV0ZS5uZXcpKXsKICAgIG1lc3NhZ2UoIm5ob29kQWRqYWNlbmN5IGZvdW5kIC0gdXNpbmcgZm9yIG5ob29kIGdyb3VwaW5nIikKICAgIG5ocy5kYS5nciA8LSAuZ3JvdXBfbmhvb2RzX2Zyb21fYWRqYWNlbmN5KG5ob29kcyh4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ob29kLmFkaj1uaG9vZEFkamFjZW5jeSh4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhLnJlcz1kYS5yZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5kYT1kYS5yZXMkU3BhdGlhbEZEUiA8IGRhLmZkciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlLmRpc2NvcmQ9bWVyZ2UuZGlzY29yZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9b3ZlcmxhcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNldC5uaG9vZHM9c3Vic2V0Lm5ob29kcykKfSBlbHNlewogICAgbmhzLmRhLmdyIDwtIC5ncm91cF9uaG9vZHNfYnlfb3ZlcmxhcChuaG9vZHMoeCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhLnJlcz1kYS5yZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLmRhPWRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPW1lcmdlLmRpc2NvcmQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9b3ZlcmxhcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0cz1iaXRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxscz1zZXFfbGVuKG5jb2woeCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQubmhvb2RzPXN1YnNldC5uaG9vZHMpICMgcmV0dXJucyBhIHZlY3RvciBncm91cCB2YWx1ZXMgZm9yIGVhY2ggbmhvb2QKfQoKbmhvb2QuZ3IgPC0gdW5pcXVlKG5ocy5kYS5ncikKIyBwZXJmb3JtIERHRSBfd2l0aGluXyBlYWNoIGdyb3VwIG9mIGNlbGxzIHVzaW5nIHRoZSBpbnB1dCBkZXNpZ24gbWF0cml4Cm1lc3NhZ2UocGFzdGUwKCJOaG9vZHMgYWdncmVnYXRlZCBpbnRvICIsIGxlbmd0aChuaG9vZC5nciksICIgZ3JvdXBzIikpCgpmYWtlLm1ldGEgPC0gZGF0YS5mcmFtZSgiQ2VsbElEIj1jb2xuYW1lcyh4KSwgIk5ob29kLkdyb3VwIj1yZXAoTkEsIG5jb2woeCkpLCAic2FtcGxlX2lkIiA9IGNvbERhdGEoeClbW3NhbXBsZXNdXSkKcm93bmFtZXMoZmFrZS5tZXRhKSA8LSBmYWtlLm1ldGEkQ2VsbElECgpmb3IoaSBpbiBzZXFfYWxvbmcobmhvb2QuZ3IpKXsKICAgIG5ob29kLnggPC0gbmhzLmRhLmdyID09IG5ob29kLmdyW2ldCiAgICAjIGdldCB0aGUgbmhvb2RzCiAgICBuaHMgPC0gbmhvb2RzKHgpCiAgICBpZighaXMubnVsbChzdWJzZXQubmhvb2RzKSl7CiAgICAgICAgbmhzIDwtIG5oc1tzdWJzZXQubmhvb2RzXQogICAgfQoKICAgIGlmKCFhbnkoaXMubmEoZmFrZS5tZXRhW3VubGlzdChuaHNbbmhvb2QueF0pLF0kTmhvb2QuR3JvdXApKSl7CiAgICAgICAgZmFrZS5tZXRhW3VubGlzdChuaHNbbmhvb2QueF0pLF0kTmhvb2QuR3JvdXBbIWlzLm5hKGZha2UubWV0YVt1bmxpc3QobmhzW25ob29kLnhdKSxdJE5ob29kLkdyb3VwKV0gPC0gTkEKICAgICAgICB9IGVsc2V7CiAgICAgICAgICAgIGZha2UubWV0YVt1bmxpc3QobmhzW25ob29kLnhdKSxdJE5ob29kLkdyb3VwIDwtIG5ob29kLmdyW2ldCiAgICAgICAgfQp9CgojIG9ubHkgY29tcGFyZSBhZ2FpbnN0IHRoZSBvdGhlciBEQSBuZWlnaGJvdXJob29kcwp4IDwtIHhbLCAhaXMubmEoZmFrZS5tZXRhJE5ob29kLkdyb3VwKV0KZmFrZS5tZXRhIDwtIGZha2UubWV0YVshaXMubmEoZmFrZS5tZXRhJE5ob29kLkdyb3VwKSwgXQoKaWYoIWlzLm51bGwoc3Vic2V0LnJvdykpewogICAgeCA8LSB4W3N1YnNldC5yb3csICwgZHJvcD1GQUxTRV0KfQoKZXhwcnMgPC0gYXNzYXkoeCwgYXNzYXkpCgojIGlmIHRoZXJlIGlzIG9ubHkgMSBncm91cCwgdGhlbiBuZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbCBuZWlnaGJvdXJob29kcwojIGFyZSBub3QgaW4gdGhpcyBncm91cCAtIG90aGVyd2lzZSBjYW4ndCBkbyBhbnkgREdFIHRlc3RpbmcKaWYobGVuZ3RoKG5ob29kLmdyKSA9PSAxKXsKICAgIGlmKHN1bShmYWtlLm1ldGEkTmhvb2QuR3JvdXAgPT0gbmhvb2QuZ3JbMV0pID09IG5yb3coZmFrZS5tZXRhKSl7CiAgICAgICAgd2FybmluZygiQWxsIGdyYXBoIG5laWdoYm91cmhvb2RzIGFyZSBpbiB0aGUgc2FtZSBncm91cCAtIGNhbm5vdCBwZXJmb3JtIERHRSB0ZXN0aW5nLiBSZXR1cm5pbmcgTlVMTCIpCiAgICAgICAgcmV0dXJuKE5VTEwpCiAgICB9Cn0KCmlmIChpc1RSVUUoYWdncmVnYXRlLnNhbXBsZXMpKSB7CiAgZmFrZS5tZXRhWywnc2FtcGxlX2dyb3VwJ10gPC0gcGFzdGUoZmFrZS5tZXRhWywic2FtcGxlX2lkIl0sIGZha2UubWV0YVssIk5ob29kLkdyb3VwIl0sIHNlcD0iXyIpCiAgCiAgc2FtcGxlX2dyX21hdCA8LSBtYXRyaXgoMCwgbnJvdz1ucm93KGZha2UubWV0YSksIG5jb2w9bGVuZ3RoKHVuaXF1ZShmYWtlLm1ldGEkc2FtcGxlX2dyb3VwKSkpCiAgY29sbmFtZXMoc2FtcGxlX2dyX21hdCkgPC0gdW5pcXVlKGZha2UubWV0YSRzYW1wbGVfZ3JvdXApCiAgcm93bmFtZXMoc2FtcGxlX2dyX21hdCkgPC0gcm93bmFtZXMoZmFrZS5tZXRhKQogIAogIGZvciAocyBpbiBjb2xuYW1lcyhzYW1wbGVfZ3JfbWF0KSkgewogICAgc2FtcGxlX2dyX21hdFt3aGljaChmYWtlLm1ldGEkc2FtcGxlX2dyb3VwID09IHMpLHNdIDwtIDEgIAogIH0KICAKICAjIyBTdW1tYXJpc2UgZXhwcmVzc2lvbiBieSBzYW1wbGUKICBleHByc19zbXAgPC0gbWF0cml4KDAsIG5yb3c9bnJvdyhleHBycyksIG5jb2w9bmNvbChzYW1wbGVfZ3JfbWF0KSkKICBpZiAoYXNzYXk9PSdjb3VudHMnKSB7CiAgICBzdW1tRnVuYyA8LSByb3dTdW1zCiAgfSBlbHNlIHsKICAgIHN1bW1GdW5jIDwtIHJvd01lYW5zCiAgfQogIAogIGZvciAoaSBpbiAxOm5jb2woc2FtcGxlX2dyX21hdCkpewogICAgaWYgKHN1bShzYW1wbGVfZ3JfbWF0WyxpXSkgPiAxKSB7CiAgICAgIGV4cHJzX3NtcFssaV0gPC0gc3VtbUZ1bmMoZXhwcnNbLHdoaWNoKHNhbXBsZV9ncl9tYXRbLGldID4gMCldKSAgCiAgICB9IGVsc2UgewogICAgICBleHByc19zbXBbLGldIDwtIGV4cHJzWyx3aGljaChzYW1wbGVfZ3JfbWF0WyxpXSA+IDApXQogICAgfQogIH0KICByb3duYW1lcyhleHByc19zbXApIDwtIHJvd25hbWVzKGV4cHJzKQogIGNvbG5hbWVzKGV4cHJzX3NtcCkgPC0gY29sbmFtZXMoc2FtcGxlX2dyX21hdCkKICAKICBzbXBfbWV0YSA8LSBkaXN0aW5jdChmYWtlLm1ldGEsIHNhbXBsZV9ncm91cCwgTmhvb2QuR3JvdXApCiAgcm93bmFtZXMoc21wX21ldGEpIDwtIHNtcF9tZXRhWywic2FtcGxlX2dyb3VwIl0KICAKICBmYWtlLm1ldGEgPC0gc21wX21ldGEKICBleHBycyA8LSBleHByc19zbXAKfQoKbWFya2VyLmxpc3QgPC0gbGlzdCgpCmkuY29udHJhc3QgPC0gYygiVGVzdFRlc3QgLSBUZXN0UmVmIikgIyBhbHdheXMgdXNlIGNvbnRyYXN0cyBmb3IgdGhpcwoKCiAgZm9yKGkgaW4gc2VxX2Fsb25nKG5ob29kLmdyKSl7CiAgICAgIGkubWV0YSA8LSBzbXBfbWV0YQogICAgICBpLm1ldGEkVGVzdCA8LSAiUmVmIgogICAgICBpLm1ldGEkVGVzdFtzbXBfbWV0YSROaG9vZC5Hcm91cCA9PSBuaG9vZC5ncltpXV0gPC0gIlRlc3QiCiAgICAgIGlmKG5jb2woZXhwcnNfc21wKSA+IDEgJiBucm93KGkubWV0YSkgPiAxKXsKICAgICAgICAgIGkuZGVzaWduIDwtIGFzLmZvcm11bGEoIiB+IDAgKyBUZXN0IikKICAgICAgICAgIGkubW9kZWwgPC0gbW9kZWwubWF0cml4KGkuZGVzaWduLCBkYXRhPWkubWV0YSkKICAgICAgICAgIHJvd25hbWVzKGkubW9kZWwpIDwtIHJvd25hbWVzKGkubWV0YSkKICAgICAgfQoKICAgICAgc2luayhmaWxlPSIvZGV2L251bGwiKQogICAgICBnYygpCiAgICAgIHNpbmsoZmlsZT1OVUxMKQoKICAgICAgaWYoYXNzYXkgPT0gImxvZ2NvdW50cyIpewogICAgICAgICAgaS5yZXMgPC0gLnBlcmZvcm1fbG9nbm9ybWFsX2RnZShleHByc19zbXAsIGkubW9kZWwsIG1vZGVsLmNvbnRyYXN0cz1pLmNvbnRyYXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lLm9mZnNldD1nZW5lLm9mZnNldCkKICAgICAgfSBlbHNlIGlmKGFzc2F5ID09ICJjb3VudHMiKXsKICAgICAgICAgIGkucmVzIDwtIC5wZXJmb3JtX2NvdW50c19kZ2UoZXhwcnNfc21wLCBpLm1vZGVsLCBtb2RlbC5jb250cmFzdHM9aS5jb250cmFzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZS5vZmZzZXQ9Z2VuZS5vZmZzZXQpCiAgICAgICAgICBjb2xuYW1lcyhpLnJlcylbbmNvbChpLnJlcyldIDwtICJhZGouUC5WYWwiCiAgICAgIH0gZWxzZXsKICAgICAgICAgIHdhcm5pbmcoIkFzc2F5IHR5cGUgaXMgbm90IGNvdW50cyBvciBsb2djb3VudHMgLSBhc3N1bWluZyAobG9nKS1ub3JtYWwgZGlzdHJpYnV0aW9uLiBVc2UgdGhlc2UgcmVzdWx0cyBhdCB5b3VyIHBlcmlsIikKICAgICAgICAgIGkucmVzIDwtIC5wZXJmb3JtX2xvZ25vcm1hbF9kZ2UoZXhwcnNfc21wLCBpLm1vZGVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbC5jb250cmFzdHM9aS5jb250cmFzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZS5vZmZzZXQ9Z2VuZS5vZmZzZXQpCiAgICAgIH0KICAgICAgCiAgICAgIAogICAgICBpLnJlcyRhZGouUC5WYWxbaXMubmEoaS5yZXMkYWRqLlAuVmFsKV0gPC0gMQogICAgICBpLnJlcyRsb2dGQ1tpcy5pbmZpbml0ZShpLnJlcyRsb2dGQyldIDwtIDAKICAgICAgCiAgICAgIGkucmVzIDwtIGkucmVzWywgYygibG9nRkMiLCAiYWRqLlAuVmFsIildCiAgICAgIGNvbG5hbWVzKGkucmVzKSA8LSBwYXN0ZShjb2xuYW1lcyhpLnJlcyksIG5ob29kLmdyW2ldLCBzZXA9Il8iKQogICAgICBtYXJrZXIubGlzdFtbcGFzdGUwKG5ob29kLmdyW2ldKV1dIDwtIGkucmVzCiAgfQoKICBtYXJrZXIuZGYgPC0gZG8uY2FsbChjYmluZC5kYXRhLmZyYW1lLCBtYXJrZXIubGlzdCkKICBjb2xuYW1lcyhtYXJrZXIuZGYpIDwtIGdzdWIoY29sbmFtZXMobWFya2VyLmRmKSwgcGF0dGVybj0iXlswLTldK1xcLiIsIHJlcGxhY2VtZW50PSIiKQogIG1hcmtlci5kZiRHZW5lSUQgPC0gcm93bmFtZXMoaS5yZXMpCmBgYAoKIyMjIyBUYWJsZSBvZiBzaWduaWZpY2FudCBER0UgZ2VuZXMgKEZEUiAxMCUpCgpgYGB7cn0KbWFya2VyLmRmW21hcmtlci5kZiRhZGouUC5WYWxfMSA8IDAuMSxdCmBgYAoKCgo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTB9IC0tPgoKPCEtLSBjb2xEYXRhKGVuZG9fbWlsbylbWyJOaG9vZEdyb3VwIl1dIDwtIGFzLmZhY3RvcihuaG9vZF9tYXJrZXJzJGdyb3Vwc1tjb2xuYW1lcyhlbmRvX21pbG8pLCJOaG9vZC5Hcm91cCJdKSAtLT4KPCEtLSBwbG90VU1BUChlbmRvX21pbG8sIGNvbG91cl9ieT0iTmhvb2RHcm91cCIpICsgZmFjZXRfd3JhcCgnY29sb3VyX2J5JykgLS0+CjwhLS0gIyBnZ3Bsb3QodW1hcF9kZiwgYWVzKFVNQVBfMSwgVU1BUF8yKSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvcj1hcy5mYWN0b3IoTmhvb2RHcm91cCkpKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0geCA9IGxpdmVyX21pbG8gLS0+CjwhLS0gZGEucmVzID0gbWlsb19yZXMgLS0+CjwhLS0gZGEuZmRyPTAuMSAtLT4KPCEtLSBhc3NheT0ibG9nY291bnRzIiAtLT4KPCEtLSBvdmVybGFwPTEgLS0+CjwhLS0gbGZjLnRocmVzaG9sZD0wLjEgLS0+CjwhLS0gbWVyZ2UuZGlzY29yZD1GQUxTRSAtLT4KPCEtLSBzdWJzZXQucm93ID0gZW5kb19odmdzIC0tPgo8IS0tIGdlbmUub2Zmc2V0PVRSVUUgLS0+CjwhLS0gcmV0dXJuLmdyb3Vwcz1UUlVFIC0tPgo8IS0tIHN1YnNldC5uaG9vZHMgPSBzdHJfZGV0ZWN0KG1pbG9fcmVzJGFubm90YXRpb25faW5kZXB0aCwgIkVuZG8iKSAtLT4KPCEtLSBuYS5mdW5jdGlvbj0ibmEucGFzcyIgLS0+CjwhLS0gY29tcHV0ZS5uZXc9RkFMU0UgLS0+CgoKPCEtLSBpZighaXMoeCwgIk1pbG8iKSl7IC0tPgo8IS0tICAgICBzdG9wKCJVbnJlY29nbmlzZWQgaW5wdXQgdHlwZSAtIG11c3QgYmUgb2YgY2xhc3MgTWlsbyIpIC0tPgo8IS0tIH0gZWxzZSBpZihhbnkoIWFzc2F5ICVpbiUgYXNzYXlOYW1lcyh4KSkpeyAtLT4KPCEtLSAgICAgc3RvcChwYXN0ZTAoIlVucmVjb2duaXNlZCBhc3NheSBzbG90OiAiLCBhc3NheSkpIC0tPgo8IS0tIH0gLS0+Cgo8IS0tIGlmKGlzLm51bGwobmEuZnVuY3Rpb24pKXsgLS0+CjwhLS0gICAgIHdhcm5pbmcoIk5VTEwgcGFzc2VkIHRvIG5hLmZ1bmN0aW9uLCB1c2luZyBuYS5wYXNzIikgLS0+CjwhLS0gICAgIG5hLmZ1bmMgPC0gZ2V0KCJuYS5wYXNzIikgLS0+CjwhLS0gfSBlbHNleyAtLT4KPCEtLSAgICAgdHJ5Q2F0Y2goeyAtLT4KPCEtLSAgICAgICAgIG5hLmZ1bmMgPC0gZ2V0KG5hLmZ1bmN0aW9uKSAtLT4KPCEtLSAgICAgfSwgd2FybmluZz1mdW5jdGlvbih3YXJuKXsgLS0+CjwhLS0gICAgICAgICB3YXJuaW5nKHdhcm4pIC0tPgo8IS0tICAgICB9LCBlcnJvcj1mdW5jdGlvbihlcnIpeyAtLT4KPCEtLSAgICAgICAgIHN0b3AocGFzdGUwKCJOQSBmdW5jdGlvbiAiLCBuYS5mdW5jdGlvbiwgIiBub3QgcmVjb2duaXNlZCIpKSAtLT4KPCEtLSAgICAgfSwgZmluYWxseT17IC0tPgo8IS0tICAgICB9KSAtLT4KPCEtLSB9IC0tPgoKPCEtLSBuLmRhIDwtIHN1bShuYS5mdW5jKGRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyKSkgLS0+CjwhLS0gaWYoIWlzLm5hKG4uZGEpICYgbi5kYSA9PSAwKXsgLS0+CjwhLS0gICAgIHN0b3AoIk5vIERBIG5laWdoYm91cmhvb2RzIGZvdW5kIikgLS0+CjwhLS0gfSAtLT4KCjwhLS0gaWYoYW55KGlzLm5hKGRhLnJlcyRTcGF0aWFsRkRSKSkpeyAtLT4KPCEtLSAgICAgd2FybmluZygiTkEgdmFsdWVzIGZvdW5kIGluIFNwYXRpYWxGRFIgdmVjdG9yIikgLS0+CjwhLS0gfSAtLT4KCjwhLS0gbWVzc2FnZShwYXN0ZTAoIkZvdW5kICIsIG4uZGEsICIgREEgbmVpZ2hib3VyaG9vZHMgYXQgRkRSICIsIGRhLmZkcioxMDAsICIlIikpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIG5ocyA9IG5ob29kcyh4KSAtLT4KPCEtLSBuaG9vZC5hZGogPSBuaG9vZEFkamFjZW5jeSh4KSAtLT4KPCEtLSBkYS5yZXMgPSBtaWxvX3JlcyAtLT4KPCEtLSBpcy5kYSA9IGRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyIC0tPgo8IS0tICAgICAjICMgYXNzdW1lIG9yZGVyIG9mIG5ocyBpcyB0aGUgc2FtZSBhcyBuaG9vZC5hZGogLS0+CjwhLS0gICAgICMgaWYoIWlzLm51bGwoc3Vic2V0Lm5ob29kcykpeyAtLT4KPCEtLSAgICAgIyAgICAgaWYobW9kZShzdWJzZXQubmhvb2RzKSAlaW4lIGMoImNoYXJhY3RlciIsICJsb2dpY2FsIiwgIm51bWVyaWMiKSl7IC0tPgo8IS0tICAgICAjICAgICAgICAgIyBmb3JjZSB1c2Ugb2YgbG9naWNhbHMgZm9yIGNvbnNpc3RlbmN5IC0tPgo8IS0tICAgICAjICAgICAgICAgaWYobW9kZShzdWJzZXQubmhvb2RzKSAlaW4lIGMoImNoYXJhY3RlciIsICJudW1lcmljIikpeyAtLT4KPCEtLSAgICAgIyAgICAgICAgICAgICBzdWIubG9nIDwtIG5hbWVzKG5ocykgJWluJSBzdWJzZXQubmhvb2RzIC0tPgo8IS0tICAgICAjICAgICAgICAgfSBlbHNleyAtLT4KPCEtLSAgICAgIyAgICAgICAgICAgICBzdWIubG9nIDwtIHN1YnNldC5uaG9vZHMgLS0+CjwhLS0gICAgICMgICAgICAgICB9IC0tPgo8IS0tICAgICAjICAtLT4KPCEtLSAgICAgIyAgICAgICAgIG5ob29kLmFkaiA8LSBuaG9vZC5hZGpbc3ViLmxvZywgc3ViLmxvZ10gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICAgICAgICAgaWYobGVuZ3RoKGlzLmRhKSA9PSBsZW5ndGgobmhzKSl7IC0tPgo8IS0tICAgICAjICAgICAgICAgICAgIG5ocyA8LSBuaHNbc3ViLmxvZ10gLS0+CjwhLS0gICAgICMgICAgICAgICAgICAgaXMuZGEgPC0gaXMuZGFbc3ViLmxvZ10gLS0+CjwhLS0gICAgICMgICAgICAgICAgICAgZGEucmVzIDwtIGRhLnJlc1tzdWIubG9nLCBdIC0tPgo8IS0tICAgICAjICAgICAgICAgfSBlbHNleyAtLT4KPCEtLSAgICAgIyAgICAgICAgICAgICBzdG9wKCJTdWJzZXR0aW5nIGBpcy5kYWAgdmVjdG9yIGxlbmd0aCBkb2VzIG5vdCBlcXVhbCBuaG9vZHMgbGVuZ3RoIikgLS0+CjwhLS0gICAgICMgICAgICAgICB9IC0tPgo8IS0tICAgICAjICAgICB9IGVsc2V7IC0tPgo8IS0tICAgICAjICAgICAgICAgc3RvcChwYXN0ZTAoIkluY29ycmVjdCBzdWJzZXR0aW5nIHZlY3RvciBwcm92aWRlZDoiLCBjbGFzcyhzdWJzZXQubmhvb2RzKSkpIC0tPgo8IS0tICAgICAjICAgICB9IC0tPgo8IS0tICAgICAjIH0gZWxzZXsgLS0+CjwhLS0gICAgICMgICAgIGlmKGxlbmd0aChpcy5kYSkgIT0gbmNvbChuaG9vZC5hZGopKXsgLS0+CjwhLS0gICAgICMgICAgICAgICBzdG9wKCJTdWJzZXR0aW5nIGBpcy5kYWAgdmVjdG9yIGxlbmd0aCBpcyBub3QgdGhlIHNhbWUgZGltZW5zaW9uIGFzIGFkamFjZW5jeSIpIC0tPgo8IS0tICAgICAjICAgICB9IC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICAtLT4KPCEtLSAgICAgIyAjIyBjaGVjayBmb3IgY29uY29yZGFudCBzaWducyAtIGFzc3VtZSBvcmRlciBpcyB0aGUgc2FtZSBhcyBuaG9vZHMgLS0+CjwhLS0gICAgICMgaWYoaXNGQUxTRShtZXJnZS5kaXNjb3JkKSl7IC0tPgo8IS0tICAgICAjICAgICBub256Lm5ocyA8LSBjb2xTdW1zKG5ob29kLmFkaikgPiAwIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lcyA8LSBleHBhbmQuZ3JpZChjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSwgYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSkpIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lc1siYWRqIl0gPC0gc2FwcGx5KDE6bnJvdyhsbF9uYW1lcyksIGZ1bmN0aW9uKHgpIG5ob29kLmFkaltsbF9uYW1lc1t4LDFdLGxsX25hbWVzW3gsMl1dKSAtLT4KPCEtLSAgICAgIyAgICAgbm9uei5wYWlycyA8LSBsbF9uYW1lc1ssImFkaiJdID4gMCAtLT4KPCEtLSAgICAgIyAgICAgIC0tPgo8IS0tICAgICAjICAgICBjb25jb3JkLnNpZ24gPC0gc2FwcGx5KCgxOm5yb3cobGxfbmFtZXMpKVtub256LnBhaXJzXSwgZnVuY3Rpb24oeCkgc2lnbihkYS5yZXNbbm9uei5uaHMsIF1bYXMubnVtZXJpYyhsbF9uYW1lc1t4LCAxXSksIF0kbG9nRkMpID09IC0tPgo8IS0tICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduKGRhLnJlc1tub256Lm5ocyxdW2FzLm51bWVyaWMobGxfbmFtZXNbeCwgMl0pLCBdJGxvZ0ZDKSkgLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICAgICBsbF9uYW1lc1ssImFkaiJdW25vbnoucGFpcnNdWyFjb25jb3JkLnNpZ25dIDwtIDAgLS0+CjwhLS0gICAgICMgICAgIG5ob29kLmFkaltub256Lm5ocywgbm9uei5uaHNdIDwtIGxsX25hbWVzWywgImFkaiJdIC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjIGlmKG92ZXJsYXAgPiAxKXsgLS0+CjwhLS0gICAgICMgICAgICMgbG9vcCBvdmVyIGFkaiBkaW1lbnNpb25zIGFuZCBtYXNrIG91dCBjZWxscyB3aXRoIGluc3VmZmljaWVudCBvdmVybGFwcGluZyBjZWxscyAtLT4KPCEtLSAgICAgIyAgICAgbm9uei5uaHMgPC0gY29sU3VtcyhuaG9vZC5hZGopID4gMCAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXMgPC0gZXhwYW5kLmdyaWQoYygxOmxlbmd0aChuaHNbbm9uei5uaHNdKSksIGMoMTpsZW5ndGgobmhzW25vbnoubmhzXSkpKSAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXNbImFkaiJdIDwtIHNhcHBseSgxOm5yb3cobGxfbmFtZXMpLCBmdW5jdGlvbih4KSBuaG9vZC5hZGpbbGxfbmFtZXNbeCwxXSxsbF9uYW1lc1t4LDJdXSkgLS0+CjwhLS0gICAgICMgICAgIG5vbnoucGFpcnMgPC0gbGxfbmFtZXNbLCJhZGoiXSA+IDAgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzW25vbnoucGFpcnMsImFkaiJdIDwtIGlmZWxzZShsbF9uYW1lc1tub256LnBhaXJzLCJhZGoiXSA8IG92ZXJsYXAsIDAsIGxsX25hbWVzW25vbnoucGFpcnMsImFkaiJdICkgLS0+CjwhLS0gICAgICMgICAgIG5ob29kLmFkaltub256Lm5ocywgbm9uei5uaHNdIDwtIGxsX25hbWVzWywgImFkaiJdIC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjIGlmKCFpcy5udWxsKGxmYy50aHJlc2hvbGQpKXsgLS0+CjwhLS0gICAgICMgICAgIG5vbnoubmhzIDwtIGNvbFN1bXMobmhvb2QuYWRqKSA+IDAgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzIDwtIGV4cGFuZC5ncmlkKGMoMTpsZW5ndGgobmhzW25vbnoubmhzXSkpLCBjKDE6bGVuZ3RoKG5oc1tub256Lm5oc10pKSkgLS0+CjwhLS0gICAgICMgICAgIGxsX25hbWVzWyJhZGoiXSA8LSBzYXBwbHkoMTpucm93KGxsX25hbWVzKSwgZnVuY3Rpb24oeCkgbmhvb2QuYWRqW2xsX25hbWVzW3gsMV0sbGxfbmFtZXNbeCwyXV0pIC0tPgo8IS0tICAgICAjICAgICBub256LnBhaXJzIDwtIGxsX25hbWVzWywiYWRqIl0gPiAwIC0tPgo8IS0tICAgICAjICAgICAgLS0+CjwhLS0gICAgICMgICAgICMgc2V0IGFkamFjZW5jeSB0byAwIGZvciBuaG9vZHMgd2l0aCBsZmMgPCB0aHJlc2hvbGQgLS0+CjwhLS0gICAgICMgICAgIGxmYy5wYXNzIDwtIHNhcHBseSgoMTpucm93KGxsX25hbWVzKSlbbm9uei5wYWlyc10sIGZ1bmN0aW9uKHgpIChhYnMoZGEucmVzW25vbnoubmhzLCBdW2FzLm51bWVyaWMobGxfbmFtZXNbeCwgMV0pLCBdJGxvZ0ZDKSA+PSBsZmMudGhyZXNob2xkKSAmIC0tPgo8IS0tICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhYnMoZGEucmVzW25vbnoubmhzLCBdW2FzLm51bWVyaWMobGxfbmFtZXNbeCwgMl0pLCBdJGxvZ0ZDKSA+PSBsZmMudGhyZXNob2xkKSkgLS0+CjwhLS0gICAgICMgICAgICAtLT4KPCEtLSAgICAgIyAgICAgbGxfbmFtZXNbLCJhZGoiXVtub256LnBhaXJzXVshbGZjLnBhc3NdIDwtIDAgLS0+CjwhLS0gICAgICMgICAgIG5ob29kLmFkaltub256Lm5ocywgbm9uei5uaHNdIDwtIGxsX25hbWVzWywgImFkaiJdIC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICMgYmluYXJpc2UgLS0+CjwhLS0gICAgICMgbmhvb2QuYWRqIDwtIGFzLm1hdHJpeCgobmhvb2QuYWRqID4gMCkgKyAwKSAtLT4KPCEtLSAgICAgIyAgLS0+CjwhLS0gICAgICMgbi5kaW0gPC0gbmNvbChuaG9vZC5hZGopIC0tPgo8IS0tICAgICAjIGlmKCFpc1N5bW1ldHJpYyhuaG9vZC5hZGopKXsgLS0+CjwhLS0gICAgICMgICAgIHN0b3AoIk92ZXJsYXAgbWF0cml4IGlzIG5vdCBzeW1tZXRyaWMiKSAtLT4KPCEtLSAgICAgIyB9IC0tPgo8IS0tICAgICAjICAtLT4KPCEtLSAgICAgIyBpZihucm93KG5ob29kLmFkaikgIT0gbmNvbChuaG9vZC5hZGopKXsgLS0+CjwhLS0gICAgICMgICAgIHN0b3AoIk5vbi1zcXVhcmUgZGlzdGFuY2UgbWF0cml4IC0gY2hlY2sgbmhvb2Qgc3Vic2V0dGluZyIpIC0tPgo8IS0tICAgICAjIH0gLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjIGcgPC0gZ3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KG5ob29kLmFkaiwgbW9kZT0idW5kaXJlY3RlZCIsIGRpYWc9RkFMU0UpIC0tPgo8IS0tICAgICAjIGdyb3VwcyA8LSBjb21wb25lbnRzKGcpJG1lbWJlcnNoaXAgLS0+CjwhLS0gICAgICMgIC0tPgo8IS0tICAgICAjICMgb25seSBrZWVwIHRoZSBncm91cHMgdGhhdCBjb250YWluID49IDEgREEgbmVpZ2hib3VyaG9vZHMgLS0+CjwhLS0gICAgICMga2VlcC5ncm91cHMgPC0gaW50ZXJzZWN0KHVuaXF1ZShncm91cHNbaXMuZGFdKSwgdW5pcXVlKGdyb3VwcykpIC0tPgo8IS0tIC5ncm91cF9uaG9vZHNfZnJvbV9hZGphY2VuY3kgPC0gZnVuY3Rpb24oeCwgZGEucmVzLCBpcy5kYSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPUZBTFNFLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxmYy50aHJlc2hvbGQ9TlVMTCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybGFwPTEsIHN1YnNldC5uaG9vZHM9TlVMTCl7IC0tPgoKPCEtLSAgICAgaWYoaXMubnVsbChuYW1lcyhuaHMpKSl7IC0tPgo8IS0tICAgICAgICAgd2FybmluZygiTm8gbmFtZXMgYXR0cmlidXRlZCB0byBuaG9vZHMuIENvbnZlcnRpbmcgaW5kaWNlcyB0byBuYW1lcyIpIC0tPgo8IS0tICAgICAgICAgbmFtZXMobmhzKSA8LSBhcy5jaGFyYWN0ZXIoYygxOmxlbmd0aChuaHMpKSkgLS0+CjwhLS0gICAgIH0gLS0+Cgo8IS0tICAgbmhfZ3JhcGggPC0gbmhvb2RHcmFwaCh4KSAtLT4KPCEtLSAgICMjIENoYW5nZSBuYW1lcyBmcm9tIG5ob29kSW5kZXggdG8gbmhvb2ROdW1iZXIgLS0+CjwhLS0gICBWKG5oX2dyYXBoKSRuYW1lIDwtIG1hdGNoKFYobmhfZ3JhcGgpJG5hbWUsIHVubGlzdChuaG9vZEluZGV4KHgpKSkgLS0+Cgo8IS0tICAgbWF4KGFzLm51bWVyaWMoVihuaF9ncmFwaCkkbmFtZSkpIC0tPgoKPCEtLSAgIGlmKCFpcy5udWxsKHN1YnNldC5uaG9vZHMpKXsgLS0+CjwhLS0gICAgIGRhLnJlcyA8LSBkYS5yZXNbc3Vic2V0Lm5ob29kcyxdICAgLS0+CjwhLS0gICB9IC0tPgoKPCEtLSAgIGtlZXAubmhvb2RzIDwtIGRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyICYgIC0tPgo8IS0tICAgICBhYnMoZGEucmVzJGxvZ0ZDKSA+IGxmYy50aHJlc2hvbGQgLS0+Cgo8IS0tICMgdW5saXN0KG5ob29kSW5kZXgoeClbc3Vic2V0Lm5ob29kc10pIC0tPgo8IS0tICMgYXMubnVtZXJpYyhWKG5oX2dyYXBoKSRuYW1lKSAlaW4lIHVubGlzdChuaG9vZEluZGV4KHgpW3N1YnNldC5uaG9vZHNdKSAmIC0tPgo8IS0tICMgICAoZGEucmVzJFNwYXRpYWxGRFIgPCBkYS5mZHIpIC0tPgoKPCEtLSAgIG5oX2dyYXBoIDwtICAtLT4KPCEtLSAgICAgaWdyYXBoOjppbmR1Y2VkX3N1YmdyYXBoKG5oX2dyYXBoLCAgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRzID0gYXMuY2hhcmFjdGVyKGRhLnJlcyROaG9vZFtrZWVwLm5ob29kc10pIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB2aWRzID0gd2hpY2goYXMubnVtZXJpYyhWKG5oX2dyYXBoKSRuYW1lKSAlaW4lIHVubGlzdChuaG9vZEluZGV4KHgpW2RhLnJlc1trZWVwLm5ob29kcywiTmhvb2QiXV0pKSAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgLS0+CjwhLS0gICBncm91cHMgPC0gY29tcG9uZW50cyhuaF9ncmFwaCkkbWVtYmVyc2hpcCAtLT4KPCEtLSAgIGtlZXAuZ3JvdXBzIDwtIGludGVyc2VjdCh1bmlxdWUoZ3JvdXBzW2lzLmRhXSksIHVuaXF1ZShncm91cHMpKSAtLT4KCgoKPCEtLSAgIHJldHVybihncm91cHNbZ3JvdXBzICVpbiUga2VlcC5ncm91cHNdKSAtLT4KPCEtLSB9IC0tPgoKCjwhLS0gZGEucmVzICU+JSAtLT4KPCEtLSAgIG11dGF0ZShrZWVwPWtlZXAubmhvb2RzKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKGxvZ0ZDLCAtbG9nMTAoU3BhdGlhbEZEUiksIGNvbG9yPWtlZXApKSArIC0tPgo8IS0tICAgZ2VvbV9wb2ludCgpIC0tPgo8IS0tIGdncmFwaChuaF9ncmFwaCkgKyBnZW9tX2VkZ2VfbGluazIoKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbGZjLnRocmVzaG9sZCA9IDAgLS0+CjwhLS0gaWYoIWlzLm51bGwobmhvb2RBZGphY2VuY3koeCkpICYgaXNGQUxTRShjb21wdXRlLm5ldykpeyAtLT4KPCEtLSAgICAgbWVzc2FnZSgibmhvb2RBZGphY2VuY3kgZm91bmQgLSB1c2luZyBmb3Igbmhvb2QgZ3JvdXBpbmciKSAtLT4KPCEtLSAgICAgbmhzLmRhLmdyIDwtIC5ncm91cF9uaG9vZHNfZnJvbV9hZGphY2VuY3koeCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhLnJlcz1taWxvX3JlcywgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLmRhPWRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2V0Lm5ob29kcyA9IHN1YnNldC5uaG9vZHMsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPW1lcmdlLmRpc2NvcmQsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybGFwPW92ZXJsYXAsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZmMudGhyZXNob2xkPWxmYy50aHJlc2hvbGQgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgLS0+CjwhLS0gfSBlbHNleyAtLT4KPCEtLSAgICAgbmhzLmRhLmdyIDwtIC5ncm91cF9uaG9vZHNfYnlfb3ZlcmxhcChuaG9vZHMoeCksIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhLnJlcz1kYS5yZXMsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLmRhPWRhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZS5kaXNjb3JkPW1lcmdlLmRpc2NvcmQsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJsYXA9b3ZlcmxhcCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAjIHJldHVybnMgYSB2ZWN0b3IgZ3JvdXAgdmFsdWVzIGZvciBlYWNoIG5ob29kIC0tPgo8IS0tIH0gLS0+Cgo8IS0tIG5ob29kLmdyIDwtIHVuaXF1ZShuaHMuZGEuZ3IpIC0tPgoKPCEtLSBuYW1lcyhuaHMuZGEuZ3IpIC0tPgo8IS0tICMgbmFtZXMobmhzLmRhLmdyKSA8LSBtYXRjaChuYW1lcyhuaHMuZGEuZ3IpLCBuaG9vZEluZGV4KHgpKSAtLT4KPCEtLSBuaHMuZGEuZ3IuYWxsIDwtIHJlcChOQSwgbGVuZ3RoKG5ob29kcyh4KSkpIC0tPgoKPCEtLSBuaHMuZGEuZ3IuYWxsW2FzLm51bWVyaWMobmFtZXMobmhzLmRhLmdyKSldIDwtIG5ocy5kYS5nciAtLT4KCgo8IS0tICMgcGVyZm9ybSBER0UgX3dpdGhpbl8gZWFjaCBncm91cCBvZiBjZWxscyB1c2luZyB0aGUgaW5wdXQgZGVzaWduIG1hdHJpeCAtLT4KPCEtLSBtZXNzYWdlKHBhc3RlMCgiTmhvb2RzIGFnZ3JlZ2F0ZWQgaW50byAiLCBsZW5ndGgobmhvb2QuZ3IpLCAiIGdyb3VwcyIpKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBjZWxsMm5ob29kcyA8LSBmdW5jdGlvbih4KXsgLS0+CjwhLS0gICBuaHMgPC0gbGFwcGx5KG5ob29kcyh4KSwgZnVuY3Rpb24obmgpIGFzLnZlY3RvcihuaCkpIC0tPgo8IS0tICAgIyBuaG9vZF9tYXQgPC0gbWF0cml4KG5yb3cgPSBuY29sKHgpLCBuY29sPWxlbmd0aChuaG9vZHMoeCkpKSAtLT4KPCEtLSAgIG5ob29kX21hdCA8LSBzYXBwbHkobmhzLCBmdW5jdGlvbihuaCkgaWZlbHNlKDE6bmNvbCh4KSAlaW4lIG5oLCAxLCAwKSkgLS0+CjwhLS0gICByZXR1cm4obmhvb2RfbWF0KSAtLT4KPCEtLSB9IC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KCjwhLS0gbmhfbWF0IDwtIGNlbGwybmhvb2RzKHgpIC0tPgo8IS0tIGZha2UubWV0YSA8LSBkYXRhLmZyYW1lKCJDZWxsSUQiPWNvbG5hbWVzKHgpKSAtLT4KPCEtLSAjIHJvd25hbWVzKGZha2UubWV0YSkgPC0gZmFrZS5tZXRhJENlbGxJRCAtLT4KCjwhLS0gZm9yKGkgaW4gc2VxX2Fsb25nKG5ob29kLmdyKSl7IC0tPgo8IS0tICAgZ3IuY2VsbHMgPC0gcm93U3VtcyhuaF9tYXRbLHdoaWNoKG5ocy5kYS5nci5hbGwgPT0gbmhvb2QuZ3JbaV0pXSkgPiAwIC0tPgo8IS0tICAgZmFrZS5tZXRhWyxwYXN0ZTAoImdyb3VwXyIsIGkpXSA8LSBnci5jZWxscyAtLT4KPCEtLSB9IC0tPgo8IS0tICMgZGltKGZha2UubWV0YVtyb3dTdW1zKG5oX21hdFssd2hpY2gobmhzLmRhLmdyLmFsbCA9PSBuaG9vZC5ncltpXSldKSA+IDAsXSkgLS0+CjwhLS0gIyAjIG5ocy5kYS5nci5hbGwgPC0gaWZlbHNlKDE6bGVuZ3RoKG5ob29kcyh4KSkgJWluJSBtYXRjaChuYW1lcyhuaHMuZGEuZ3IpLCBuaG9vZEluZGV4KHgpKSwgbmhzLmRhLmdyLCBOQSkgLS0+CjwhLS0gIyBmb3IoaSBpbiBzZXFfYWxvbmcobmhvb2QuZ3IpKXsgLS0+CjwhLS0gIyAgICAgbmhvb2QueCA8LSBuaHMuZGEuZ3IuYWxsID09IG5ob29kLmdyW2ldIC0tPgo8IS0tICMgICAgIG5ob29kLnhbaXMubmEobmhvb2QueCldIDwtIEZBTFNFIC0tPgo8IS0tICMgICAgIGZha2UubWV0YVt1bmxpc3Qobmhvb2RzKHgpW2RhLnJlcyRTcGF0aWFsRkRSIDwgZGEuZmRyXVtuaG9vZC54XSksIHBhc3RlMCgiZ3JvdXBfIiwgaSldIDwtIG5ob29kLmdyW2ldIC0tPgo8IS0tICMgfSAtLT4KCjwhLS0gZmFrZS5tZXRhIDwtIC0tPgo8IS0tICAgZmFrZS5tZXRhICU+JSAtLT4KPCEtLSAgIG11dGF0ZShOaG9vZC5Hcm91cCA9IGlmZWxzZShncm91cF8xLCAxLCBpZmVsc2UoZ3JvdXBfMiwgMiwgTkEpKSkgIC0tPgo8IS0tIHJvd25hbWVzKGZha2UubWV0YSkgPC0gZmFrZS5tZXRhJENlbGxJRCAtLT4KCjwhLS0gY29sRGF0YShlbmRvX21pbG8pW1siZ3JvdXBfMSJdXSA8LSBhcy5mYWN0b3IoZmFrZS5tZXRhW2NvbG5hbWVzKGVuZG9fbWlsbyksImdyb3VwXzEiXSkgLS0+CjwhLS0gY29sRGF0YShlbmRvX21pbG8pW1siZ3JvdXBfMiJdXSA8LSBhcy5mYWN0b3IoZmFrZS5tZXRhW2NvbG5hbWVzKGVuZG9fbWlsbyksImdyb3VwXzIiXSkgLS0+CjwhLS0gY29sRGF0YShlbmRvX21pbG8pW1siTmhvb2RHcm91cCJdXSA8LSBhcy5mYWN0b3IoZmFrZS5tZXRhW2NvbG5hbWVzKGVuZG9fbWlsbyksIk5ob29kR3JvdXAiXSkgLS0+CjwhLS0gcGxvdFVNQVAoZW5kb19taWxvLCBjb2xvdXJfYnk9Ik5ob29kR3JvdXAiKSAtLT4KCjwhLS0gYGBgIC0tPgoKCgo8IS0tIGBgYHtyfSAtLT4KCjwhLS0gIyBvbmx5IGNvbXBhcmUgYWdhaW5zdCB0aGUgb3RoZXIgREEgbmVpZ2hib3VyaG9vZHMgLS0+CjwhLS0geCA8LSB4WywgIWlzLm5hKGZha2UubWV0YSROaG9vZC5Hcm91cCldIC0tPgo8IS0tIGZha2UubWV0YSA8LSBmYWtlLm1ldGFbIWlzLm5hKGZha2UubWV0YSROaG9vZC5Hcm91cCksIF0gLS0+Cgo8IS0tIGlmKCFpcy5udWxsKHN1YnNldC5yb3cpKXsgLS0+CjwhLS0gICAgIHggPC0geFtzdWJzZXQucm93LCAsIGRyb3A9RkFMU0VdIC0tPgo8IS0tIH0gLS0+Cgo8IS0tICAgICBleHBycyA8LSBhc3NheSh4LCBhc3NheSkgLS0+Cgo8IS0tICAgICBtYXJrZXIubGlzdCA8LSBsaXN0KCkgLS0+CjwhLS0gICAgIGkuY29udHJhc3QgPC0gYygiVGVzdFRlc3QgLSBUZXN0UmVmIikgIyBhbHdheXMgdXNlIGNvbnRyYXN0cyBmb3IgdGhpcyAtLT4KCjwhLS0gICAgICMgaWYgdGhlcmUgaXMgb25seSAxIGdyb3VwLCB0aGVuIG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgYWxsIG5laWdoYm91cmhvb2RzIC0tPgo8IS0tICAgICAjIGFyZSBub3QgaW4gdGhpcyBncm91cCAtIG90aGVyd2lzZSBjYW4ndCBkbyBhbnkgREdFIHRlc3RpbmcgLS0+CjwhLS0gICAgIGlmKGxlbmd0aChuaG9vZC5ncikgPT0gMSl7IC0tPgo8IS0tICAgICAgICAgaWYoc3VtKGZha2UubWV0YSROaG9vZC5Hcm91cCA9PSBuaG9vZC5nclsxXSkgPT0gbnJvdyhmYWtlLm1ldGEpKXsgLS0+CjwhLS0gICAgICAgICAgICAgd2FybmluZygiQWxsIGdyYXBoIG5laWdoYm91cmhvb2RzIGFyZSBpbiB0aGUgc2FtZSBncm91cCAtIGNhbm5vdCBwZXJmb3JtIERHRSB0ZXN0aW5nLiBSZXR1cm5pbmcgTlVMTCIpIC0tPgo8IS0tICAgICAgICAgICAgIHJldHVybihOVUxMKSAtLT4KPCEtLSAgICAgICAgIH0gLS0+CjwhLS0gICAgIH0gLS0+Cgo8IS0tICAgICBmb3IoaSBpbiBzZXFfYWxvbmcobmhvb2QuZ3IpKXsgLS0+CjwhLS0gICAgICAgICBpLm1ldGEgPC0gZmFrZS5tZXRhIC0tPgo8IS0tICAgICAgICAgaS5tZXRhJFRlc3QgPC0gIlJlZiIgLS0+CjwhLS0gICAgICAgICBpLm1ldGEkVGVzdFtmYWtlLm1ldGEkTmhvb2QuR3JvdXAgPT0gbmhvb2QuZ3JbaV1dIDwtICJUZXN0IiAtLT4KCjwhLS0gICAgICAgICBpZihuY29sKGV4cHJzKSA+IDEgJiBucm93KGkubWV0YSkgPiAxKXsgLS0+CjwhLS0gICAgICAgICAgICAgaS5kZXNpZ24gPC0gYXMuZm9ybXVsYSgiIH4gMCArIFRlc3QiKSAtLT4KPCEtLSAgICAgICAgICAgICBpLm1vZGVsIDwtIG1vZGVsLm1hdHJpeChpLmRlc2lnbiwgZGF0YT1pLm1ldGEpIC0tPgo8IS0tICAgICAgICAgICAgIHJvd25hbWVzKGkubW9kZWwpIDwtIHJvd25hbWVzKGkubWV0YSkgLS0+CjwhLS0gICAgICAgICB9IC0tPgoKPCEtLSAgICAgICAgIHNpbmsoZmlsZT0iL2Rldi9udWxsIikgLS0+CjwhLS0gICAgICAgICBnYygpIC0tPgo8IS0tICAgICAgICAgc2luayhmaWxlPU5VTEwpIC0tPgoKPCEtLSAgICAgICAgIGlmKGFzc2F5ID09ICJsb2djb3VudHMiKXsgLS0+CjwhLS0gICAgICAgICAgICAgaS5yZXMgPC0gLnBlcmZvcm1fbG9nbm9ybWFsX2RnZShleHBycywgaS5tb2RlbCwgbW9kZWwuY29udHJhc3RzPWkuY29udHJhc3QsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZS5vZmZzZXQ9Z2VuZS5vZmZzZXQpIC0tPgo8IS0tICAgICAgICAgfSBlbHNlIGlmKGFzc2F5ID09ICJjb3VudHMiKXsgLS0+CjwhLS0gICAgICAgICAgICAgaS5yZXMgPC0gLnBlcmZvcm1fY291bnRzX2RnZShleHBycywgaS5tb2RlbCwgbW9kZWwuY29udHJhc3RzPWkuY29udHJhc3QsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZS5vZmZzZXQ9Z2VuZS5vZmZzZXQpIC0tPgo8IS0tICAgICAgICAgfSBlbHNleyAtLT4KPCEtLSAgICAgICAgICAgICB3YXJuaW5nKCJBc3NheSB0eXBlIGlzIG5vdCBjb3VudHMgb3IgbG9nY291bnRzIC0gYXNzdW1pbmcgKGxvZyktbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVXNlIHRoZXNlIHJlc3VsdHMgYXQgeW91ciBwZXJpbCIpIC0tPgo8IS0tICAgICAgICAgICAgIGkucmVzIDwtIC5wZXJmb3JtX2xvZ25vcm1hbF9kZ2UoZXhwcnMsIGkubW9kZWwsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWwuY29udHJhc3RzPWkuY29udHJhc3QsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZS5vZmZzZXQ9Z2VuZS5vZmZzZXQpIC0tPgo8IS0tICAgICAgICAgfSAtLT4KCjwhLS0gICAgICAgICBpLnJlcyRhZGouUC5WYWxbaXMubmEoaS5yZXMkYWRqLlAuVmFsKV0gPC0gMSAtLT4KPCEtLSAgICAgICAgIGkucmVzJGxvZ0ZDW2lzLmluZmluaXRlKGkucmVzJGxvZ0ZDKV0gPC0gMCAtLT4KCjwhLS0gICAgICAgICBpLnJlcyA8LSBpLnJlc1ssIGMoImxvZ0ZDIiwgImFkai5QLlZhbCIpXSAtLT4KPCEtLSAgICAgICAgIGNvbG5hbWVzKGkucmVzKSA8LSBwYXN0ZShjb2xuYW1lcyhpLnJlcyksIG5ob29kLmdyW2ldLCBzZXA9Il8iKSAtLT4KPCEtLSAgICAgICAgIG1hcmtlci5saXN0W1twYXN0ZTAobmhvb2QuZ3JbaV0pXV0gPC0gaS5yZXMgLS0+CjwhLS0gICAgIH0gLS0+Cgo8IS0tICAgICBtYXJrZXIuZGYgPC0gZG8uY2FsbChjYmluZC5kYXRhLmZyYW1lLCBtYXJrZXIubGlzdCkgLS0+CjwhLS0gICAgIGNvbG5hbWVzKG1hcmtlci5kZikgPC0gZ3N1Yihjb2xuYW1lcyhtYXJrZXIuZGYpLCBwYXR0ZXJuPSJeWzAtOV0rXFwuIiwgcmVwbGFjZW1lbnQ9IiIpIC0tPgo8IS0tICAgICBtYXJrZXIuZGYkR2VuZUlEIDwtIHJvd25hbWVzKGkucmVzKSAtLT4KCjwhLS0gICAgIGlmKGlzVFJVRShyZXR1cm4uZ3JvdXBzKSl7IC0tPgo8IS0tICAgICAgICAgb3V0Lmxpc3QgPC0gbGlzdCgiZ3JvdXBzIj1mYWtlLm1ldGEsICJkZ2UiPW1hcmtlci5kZikgLS0+CjwhLS0gICAgICAgICByZXR1cm4ob3V0Lmxpc3QpIC0tPgo8IS0tICAgICB9ZWxzZXsgLS0+CjwhLS0gICAgICAgICByZXR1cm4obWFya2VyLmRmKSAtLT4KPCEtLSAgICAgfSAtLT4KPCEtLSBuaG9vZF9tYXJrZXJzIDwtIG91dC5saXN0IC0tPgo8IS0tIHN1bShtYXJrZXIuZGYkYWRqLlAuVmFsXzEgPCAwLjAwMSkgLS0+Cgo8IS0tIGJjZWxsX2dlbmVzIDwtIGMoJ01TNEExJywgIkNEMTkiLCAiRkNHUjJCIiwgIklHSEExIikgLS0+Cgo8IS0tIHBsb3RVTUFQKGVuZG9fbWlsbywgY29sb3VyX2J5PWJjZWxsX2dlbmVzWzNdKSAtLT4KCjwhLS0gYGBgIC0tPgoKIyMjIyBWaXN1YWxpemUgYXMgdm9sY2FubyAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWFya2VyLmRmICU+JQogICBtdXRhdGUoYWRqLlAuVmFsXzEgPSBpZmVsc2UoLSBsb2cxMChhZGouUC5WYWxfMSkgPiAzMDAsIDFlLTMwMCwgYWRqLlAuVmFsXzEpKSAlPiUKICBtdXRhdGUobGFiZWw9aWZlbHNlKC1sb2cxMChhZGouUC5WYWxfMSkgPiAxLjcsIEdlbmVJRCwgTkEpKSAlPiUKICBnZ3Bsb3QoYWVzKGxvZ0ZDXzIsIC1sb2cxMChhZGouUC5WYWxfMSksIAogICAgICAgICAgICAgIyBjb2xvcj1oaWdobGlnaHQKICAgICAgICAgICAgICkpICsgCiAgZ2VvbV9wb2ludCgpICsKICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsPWxhYmVsKSkgKwogIHhsYWIoImxvZ0ZDIikgKyB5bGFiKCItIGxvZzEwKEFkai4gUCB2YWx1ZSkiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMjIpCiAgCiAgCmBgYAoKIyMjIyBWaXN1YWxpemUgYXMgaGVhdG1hcCAKKGdlbmUgZXhwcmVzc2lvbiB2YWx1ZXMgYXJlIHNjYWxlZCBiZXR3ZWVuIDAgYW5kIDEgZm9yIGVhY2ggZ2VuZSkKCjwhLS0gYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9IC0tPgo8IS0tIG1hcmtlcl9nZW5lc19kb3duIDwtIG1hcmtlci5kZiAlPiUgLS0+CjwhLS0gICBkcGx5cjo6ZmlsdGVyKGFkai5QLlZhbF8xIDwgMC4xICYgbG9nRkNfMiA8IC0xKSAlPiUgLS0+CjwhLS0gICBwdWxsKEdlbmVJRCkgLS0+CgoKPCEtLSBwbG90Tmhvb2RFeHByZXNzaW9uREEobGl2ZXJfbWlsbywgbWlsb19yZXMsIG1hcmtlcl9nZW5lc19kb3duLCBjbHVzdGVyX2ZlYXR1cmVzID0gVFJVRSwgIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3RvXzEgPSBUUlVFLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgc3Vic2V0Lm5ob29kcyA9IG1pbG9fcmVzJGFubm90YXRpb25fbGluZWFnZT09IkNob2xhbmdpb2N5dGVzIiwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBUUlVFIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICApICsgLS0+CjwhLS0gICB5bGFiKCJERSBnZW5lcyIpICsgLS0+CjwhLS0gICAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0yMiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTI0KSkgKyAtLT4KPCEtLSAgIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEsNCkpIC0tPgo8IS0tIGBgYCAtLT4KCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1hcmtlcl9nZW5lc191cCA8LSBtYXJrZXIuZGYgJT4lCiAgZHBseXI6OmZpbHRlcihhZGouUC5WYWxfMSA8IDAuMDEgJiBsb2dGQ18yID4gMikgJT4lCiAgcHVsbChHZW5lSUQpCgoKcGxvdE5ob29kRXhwcmVzc2lvbkRBKGxpdmVyX21pbG8sIG1pbG9fcmVzLCBtYXJrZXJfZ2VuZXNfdXAsIGNsdXN0ZXJfZmVhdHVyZXMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC4xLAogICAgICAgICAgICAgICAgICAgICAgc2NhbGVfdG9fMSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQubmhvb2RzID0gbWlsb19yZXMkYW5ub3RhdGlvbl9saW5lYWdlPT0iQ2hvbGFuZ2lvY3l0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICkgKwogIHlsYWIoIkRFIGdlbmVzIikgKwogICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTIyKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjQpKSArCiAgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMSwxMCkpCgoKYGBgCgojIyMgR08gdGVybSBhbmFseXNpcwoKYGBge3J9Cm1hcmtlcl9nZW5lc191cCA8LSBtYXJrZXIuZGYgJT4lCiAgZHBseXI6OmZpbHRlcihhZGouUC5WYWxfMSA8IDAuMSAmIGxvZ0ZDXzIgPiAwKSAlPiUKICBwdWxsKEdlbmVJRCkKCmVtX3VwIDwtIGVucmljaGVyKG1hcmtlcl9nZW5lc191cCwgVEVSTTJHRU5FPW1fdDJnLCBwQWRqdXN0TWV0aG9kID0gImZkciIsIAogICAgICAgICAgICAgICAgICB1bml2ZXJzZSA9IHJvd25hbWVzKGxpdmVyX21pbG8pCiAgICAgICAgICAgICAgICAgICkKCmVtX3Jlc191cCA8LSBlbV91cEByZXN1bHRbZW1fdXBAcmVzdWx0JHF2YWx1ZSA8IDAuMDUsXSAlPiUKICBkcGx5cjo6c2VsZWN0KC0gYyhEZXNjcmlwdGlvbikpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTE1fQoKZW1fcmVzX3VwICU+JQogIHRvcF9uKDQwLCAtbG9nMTAocXZhbHVlKSkgJT4lCiAgbXV0YXRlKFRlcm09ZmFjdG9yKElELCBsZXZlbHM9cmV2KHVuaXF1ZShJRCkpKSkgJT4lCiAgZ2dwbG90KGFlcyhUZXJtLCAtbG9nMTAocXZhbHVlKSkpICsKICBnZW9tX3BvaW50KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgeGxhYigiR08gQmlvbG9naWNhbCBGdW5jdGlvbiIpICsgeWxhYigiLWxvZzEwKEFkai4gcC12YWx1ZSkiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplPTE0KSArCiAgZ2d0aXRsZSgiTWFya2VycyBvZiBoZWFsdGh5IikKYGBgCgojIyMgRnVsbCBHTyBlbnJpY2htZW50IC0gdXAgaW4gY2lycmhvdGljCihgZ2VuZUlEYCBjb2x1bW4gaW5kaWNhdGVzIHdoaWNoIGdlbmVzIGJlbG9uZyB0byBnZW5lIG9udG9sb2d5KQpgYGB7cn0KZW1fcmVzX3VwCmBgYAoKLS0tCgpBc3NlbWJsZSBmaWd1cmUKYGBge3IsIGZpZy5oZWlnaHQ9MjUsIGZpZy53aWR0aD0xOX0KZmlnNF9ib3R0b20gPC0gKChmaWc0X2JsZWZ0ICsgcGxvdF9sYXlvdXQoKSkgfAogICAgICAoKGZpZzRfYnJpZ2h0MSArIHBsb3RfbGF5b3V0KHRhZ19sZXZlbCA9ICdrZWVwJykpIC8gKGZpZzRfYmJyaWdodCArIHBsb3RfbGF5b3V0KCkpKSArCiAgICAgIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEsMS42KSkKICAgKSArCiAgcGxvdF9sYXlvdXQod2lkdGhzPWMoMSwxLjIpKQoKKGZpZzRfdG9wIC8gZmlnNF9ib3R0b20pICsKICBwbG90X2xheW91dChoZWlnaHRzPWMoMSwxLjgpKSAgKwogIGdnc2F2ZSgifi9taWxvX291dHB1dC9maWc0LnBkZiIsIGhlaWdodCA9IDI2LCB3aWR0aCA9IDIyLCB1c2VEaW5nYmF0cz1GQUxTRSkKICAjIGdnc2F2ZSgifi9taWxvL21zL2ZpZ3VyZXMvZmlncy9maWd1cmU1LnBkZiIsIGhlaWdodCA9IDI2LCB3aWR0aCA9IDIyLCB1c2VEaW5nYmF0cz1GQUxTRSkKYGBgCgpBc3NlbWJsZSBzdXBwbGVtZW50YXJ5IGZpZ3VyZQoKYGBge3IsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTd9CnAxIDwtIHBsb3RfZ3JpZChwdmFsX2hpc3QsCiAgICAgICAgICAgICAgICB2b2xjYW5vICsgeWxhYigiLSBsb2cxMChTcGF0aWFsIEZEUikiKSwKICAgICAgICAgICAgICAgIGZyYWNfaGlzdCwgbnJvdz0xLAogICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiKSkKY293cGxvdDo6cGxvdF9ncmlkKHAxLCBnb19wbG90LCByZWxfaGVpZ2h0cyA9IGMoMSwxLjUpLCBuY29sPTEsIGxhYmVscyA9IGMoIiIsICJEIikpICsKICBnZ3NhdmUoIn4vbWlsby9tcy9zdXBwbGVtZW50L3N1cHBsX2ZpZ3Mvc3VwcGxfZmlnNi5wZGYiLCBoZWlnaHQgPSA3LCB3aWR0aD04KQogIGdnc2F2ZSgifi9taWxvX291dHB1dC9saXZlcl9zdXBwbGVtZW50YXJ5LnBuZyIsIGhlaWdodCA9IDcsIHdpZHRoPTgpCgpgYGAKCjwhLS0gTGV0J3MgY2hlY2sgdGhlIGdlbmVzIGlkZW50aWZpZWQgYXMgbWFya2VycyBmb3IgdGhlIGRpc2Vhc2Ugc3VidHlwZXMuIEFyZSB0aGV5IHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4gREEgbmVpZ2hib3VyaG9vZHM/IFllcyB0aGV5IGFyZSEgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkaXNlYXNlX2VuZG9fbWFya2VycyA8LSBjKCJBQ0tSMSIsICdDRDM0JywiVldBMSIpIC0tPgoKPCEtLSBkYXRhLmZyYW1lKG1hcmtlcnMkbmVnTG9nRkNfMikgJT4lIC0tPgo8IS0tICAgZmlsdGVyKEZEUiA8IDAuMDUpICU+JSAtLT4KPCEtLSAgIC5bZGlzZWFzZV9lbmRvX21hcmtlcnMsXSAtLT4KCjwhLS0gZGF0YS5mcmFtZShtYXJrZXJzJG5lZ0xvZ0ZDXzEpICU+JSAtLT4KPCEtLSAgIGZpbHRlcihGRFIgPCAwLjA1KSAlPiUgLS0+CjwhLS0gICAuW2Rpc2Vhc2VfZW5kb19tYXJrZXJzLF0gLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBWaXN1YWxpemUgc29tZSBvZiB0aGUgbWFya2VycyB0aGF0IGRpZmZlcmVudGlhdGUgREEgbmVpZ2hib3VyaG9vZHMsIGJ5IHBsb3R0aW5nIHRoZSBwZXJjZW50IG9mIGNlbGxzIGV4cHJlc3NpbmcgZWFjaCBnZW5lIGluIGEgbmhvb2QuIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyMgRGVmaW5lIHBsb3R0aW5nIGZ1bmN0aW9ucyAtLT4KPCEtLSAuY2FsY3VsYXRlX25ob29kX3BlcmNfZXhwcmVzc2lvbiA8LSBmdW5jdGlvbihtaWxvLCBuaG9vZHMsIGdlbmUpeyAtLT4KPCEtLSAgIGdlbmVfY250cyA8LSBjb3VudHMobWlsbylbZ2VuZSxdIC0tPgo8IS0tICAgcGVyY19leHByIDwtIHNhcHBseShuaG9vZHMobWlsbylbbmhvb2RzXSwgZnVuY3Rpb24oeCkgc3VtKGdlbmVfY250c1t4XT4wKS9sZW5ndGgoeCkpIC0tPgo8IS0tICAgcGVyY19leHByIDwtIHNldE5hbWVzKHBlcmNfZXhwciwgbmhvb2RzKSAtLT4KPCEtLSAgIHJldHVybihwZXJjX2V4cHIpIC0tPgo8IS0tICAgfSAtLT4KCjwhLS0gLnBsb3Rfbmhvb2RfZXhwcmVzc2lvbiA8LSBmdW5jdGlvbihtaWxvLCBuaG9vZHMsIGZlYXR1cmVzKXsgLS0+CjwhLS0gICBwZXJjX2V4cHJfbWF0IDwtIHNhcHBseShmZWF0dXJlcywgIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgLmNhbGN1bGF0ZV9uaG9vZF9wZXJjX2V4cHJlc3Npb24obWlsbywgbmhvb2RzLCB4KSkgLS0+Cgo8IS0tICAgcGxfZGYgPC0gZGF0YS5mcmFtZShwZXJjX2V4cHJfbWF0KSAlPiUgLS0+CjwhLS0gICAgIHJvd25hbWVzX3RvX2NvbHVtbigiTmhvb2QiKSAlPiUgLS0+CjwhLS0gICAgIG11dGF0ZShOaG9vZD1hcy5kb3VibGUoTmhvb2QpKSAlPiUgLS0+CjwhLS0gICAgIGxlZnRfam9pbihtaWxvX3JlcykgJT4lIC0tPgo8IS0tICAgICBtdXRhdGUobG9nRkNfcmFuaz1yYW5rKGxvZ0ZDKSkgIC0tPgoKPCEtLSAgIHBsX3RvcCA8LSBwbF9kZiAlPiUgLS0+CjwhLS0gICAgICAgbXV0YXRlKGlzX3NpZ25pZiA9IGlmZWxzZShTcGF0aWFsRkRSIDwgMC4xLCAiU3BhdGlhbEZEUiA8IDAuMSIsIE5BKSkgJT4lIC0tPgo8IS0tICAgICAgIGdncGxvdChhZXMobG9nRkNfcmFuaywgbG9nRkMpKSArIC0tPgo8IS0tICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsgLS0+CjwhLS0gICAgICAgZ2VvbV9wb2ludChzaXplPTAuMikgKyAtLT4KPCEtLSAgICAgICBnZW9tX3BvaW50KGRhdGE9LiU+JSBmaWx0ZXIoIWlzLm5hKGlzX3NpZ25pZikpLCBhZXMoY29sb3I9aXNfc2lnbmlmKSwgc2l6ZT0wLjUpICsgLS0+CjwhLS0gICAgICAgdGhlbWVfYncoKSArIC0tPgo8IS0tICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9InJlZCIsIG5hbWU9IiIpICsgLS0+CjwhLS0gICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSAtLT4KCjwhLS0gICBwbF9ib3R0b20gPC0gcGxfZGYgJT4lIC0tPgo8IS0tICAgICBwaXZvdF9sb25nZXIoY29scz1mZWF0dXJlcywgbmFtZXNfdG89J2ZlYXR1cmUnLCB2YWx1ZXNfdG89InBlcmNfZXhwcmVzc2VkIikgJT4lIC0tPgo8IS0tICAgICBtdXRhdGUoZmVhdHVyZT1mYWN0b3IoZmVhdHVyZSwgbGV2ZWxzPWZlYXR1cmVzKSkgJT4lIC0tPgo8IS0tICAgICBnZ3Bsb3QoYWVzKGxvZ0ZDX3JhbmssIGZlYXR1cmUsIGZpbGw9cGVyY19leHByZXNzZWQpKSArICAtLT4KPCEtLSAgICAgZ2VvbV90aWxlKCkgKyAtLT4KPCEtLSAgICAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uPSJtYWdtYSIpICsgLS0+CjwhLS0gICAgIGdnYmlvOjp0aGVtZV9jbGVhcigpIC0tPgoKPCEtLSAgIChwbF90b3AgLyBwbF9ib3R0b20pICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMSwyKSkgLS0+CjwhLS0gfSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEyfSAtLT4KPCEtLSBlbmRvX25ob29kcyA8LSBlbmRvX3JlcyAlPiUgIHB1bGwoTmhvb2QpIC0tPgoKPCEtLSAjIyBTZWxlY3QgZ2VuZXMgYW5kIHNvcnQgYnkgQVVDIC0tPgo8IS0tIGZlYXRzX25lZzIgPC0gLS0+CjwhLS0gICBkYXRhLmZyYW1lKG1hcmtlcnMkbmVnTG9nRkNfMikgJT4lICAtLT4KPCEtLSAgIHRvcF9uKDUwLCAtIGxvZzEwKEZEUikpICU+JSAtLT4KPCEtLSAgIGFycmFuZ2UoQVVDLnBvc0xvZ0ZDXzEpICU+JSAtLT4KPCEtLSAgIHJvd25hbWVzKCkgLS0+Cgo8IS0tIC5wbG90X25ob29kX2V4cHJlc3Npb24obGl2ZXJfbWlsbywgZW5kb19uaG9vZHMsIGZlYXR1cmVzPWZlYXRzKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIEFzIGRlc2NyaWJlZCBpbiB0aGUgcGFwZXIsIHdlIGhhdmUgdGhhdCBnZW5lcyBhc3NvY2lhdGVkIHdpdGggZXh0cmFjZWxsdWxhciBtYXRyaXggb3JnYW5pemF0aW9uIChlLmcuIFZJTSwgKSBhcmUgb3ZlciBleHByZXNzZWQgIC0tPgoKCjwhLS0gYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03fSAtLT4KPCEtLSAjIyBTZWxlY3QgZ2VuZXMgYW5kIHNvcnQgYnkgQVVDIC0tPgo8IS0tIGZlYXRzX25lZzEgPC0gLS0+CjwhLS0gICBkYXRhLmZyYW1lKG1hcmtlcnMkbmVnTG9nRkNfMSkgJT4lICAtLT4KPCEtLSAgIHRvcF9uKDUwLCAtIGxvZzEwKEZEUikpICU+JSAtLT4KPCEtLSAgIGFycmFuZ2UoQVVDLnBvc0xvZ0ZDXzEpICU+JSAtLT4KPCEtLSAgIHJvd25hbWVzKCkgLS0+Cgo8IS0tIC5wbG90X25ob29kX2V4cHJlc3Npb24obGl2ZXJfbWlsbywgZW5kb19uaG9vZHMsIGZlYXR1cmVzPWZlYXRzKSAtLT4KCjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTd9IC0tPgo8IS0tIGZlYXRzX25lZzF2c05lZzIgPC0gLS0+CjwhLS0gICBkYXRhLmZyYW1lKG1hcmtlcnMkbmVnTG9nRkNfMSkgJT4lICAtLT4KPCEtLSAgIHRvcF9uKDUwLCAtIGxvZzEwKEZEUikpICU+JSAtLT4KPCEtLSAgIGFycmFuZ2UoQVVDLm5lZ0xvZ0ZDXzIpICU+JSAtLT4KPCEtLSAgIHJvd25hbWVzKCkgLS0+Cgo8IS0tIC5wbG90X25ob29kX2V4cHJlc3Npb24obGl2ZXJfbWlsbywgZW5kb19uaG9vZHMsIGZlYXR1cmVzPWZlYXRzX25lZzF2c05lZzIpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIExvb2sganVzdCBhdCBFbmRvdGhlbGlhICg1KSB3aGVyZSB5b3UgaGF2ZSBib3RoIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBmb2xkLWNoYW5nZXMgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBlbmRvNV9uaG9vZHMgPC0gbWlsb19yZXMgJT4lICAtLT4KPCEtLSAgIGZpbHRlcihhbm5vdGF0aW9uX2luZGVwdGg9PSJFbmRvdGhlbGlhICg1KSIgJiBhbm5vdGF0aW9uX2luZGVwdGhfZnJhY3Rpb24gPiAwLjcpICU+JSAtLT4KPCEtLSAgIHB1bGwoTmhvb2QpIC0tPgoKPCEtLSBwZXJjX2V4cHJfbWF0IDwtIHNhcHBseShmZWF0dXJlcywgIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIC5jYWxjdWxhdGVfbmhvb2RfcGVyY19leHByZXNzaW9uKGxpdmVyX21pbG8sIGVuZG81X25ob29kcywgeCkpIC0tPgoKPCEtLSBwbF9kZiA8LSBkYXRhLmZyYW1lKHBlcmNfZXhwcl9tYXQpICU+JSAtLT4KPCEtLSAgIHJvd25hbWVzX3RvX2NvbHVtbigiTmhvb2QiKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoTmhvb2Q9YXMuZG91YmxlKE5ob29kKSkgJT4lIC0tPgo8IS0tICAgbGVmdF9qb2luKG1pbG9fcmVzKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUobG9nRkNfcmFuaz1yYW5rKGxvZ0ZDKSkgIC0tPgoKPCEtLSBwbF90b3AgPC0gcGxfZGYgJT4lIC0tPgo8IS0tICAgICBtdXRhdGUoaXNfc2lnbmlmID0gaWZlbHNlKFNwYXRpYWxGRFIgPCAwLjEsICJTcGF0aWFsRkRSIDwgMC4xIiwgTkEpKSAlPiUgLS0+CjwhLS0gICAgIGdncGxvdChhZXMobG9nRkNfcmFuaywgbG9nRkMpKSArIC0tPgo8IS0tICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0yKSArIC0tPgo8IS0tICAgICBnZW9tX3BvaW50KHNpemU9MC4yKSArIC0tPgo8IS0tICAgICBnZW9tX3BvaW50KGRhdGE9LiU+JSBmaWx0ZXIoIWlzLm5hKGlzX3NpZ25pZikpLCBhZXMoY29sb3I9aXNfc2lnbmlmKSwgc2l6ZT0wLjUpICsgLS0+CjwhLS0gICAgIHRoZW1lX2J3KCkgKyAtLT4KPCEtLSAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0icmVkIiwgbmFtZT0iIikgKyAtLT4KPCEtLSAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSAtLT4KCjwhLS0gcGxfYm90dG9tIDwtIHBsX2RmICU+JSAtLT4KPCEtLSAgIHBpdm90X2xvbmdlcihjb2xzPWZlYXR1cmVzLCBuYW1lc190bz0nZmVhdHVyZScsIHZhbHVlc190bz0icGVyY19leHByZXNzZWQiKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKGxvZ0ZDX3JhbmssIGZlYXR1cmUsIGZpbGw9cGVyY19leHByZXNzZWQpKSArICAtLT4KPCEtLSAgIGdlb21fdGlsZSgpICsgLS0+CjwhLS0gICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb249Im1hZ21hIikgKyAtLT4KPCEtLSAgIHRoZW1lX2NsZWFyKCkgLS0+Cgo8IS0tIChwbF90b3AgLyBwbF9ib3R0b20pICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMSwyKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBIb3cgdG8gZmluZCBhc3NvY2lhdGlvbiBkZSBub3ZvIGluIEVuZG8gNT8gLS0+Cgo8IS0tIGBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04fSAtLT4KPCEtLSAjIyBGaW5kIG1vc3QgaGlnaGx5IHZhcmlhYmxlIGdlbmVzIGluIHRoaXMgY2x1c3RlciAtLT4KPCEtLSBlbmRvNV9taWxvIDwtIGxpdmVyX21pbG9bLHdoaWNoKGNvbERhdGEobGl2ZXJfbWlsbylbWyJhbm5vdGF0aW9uX2luZGVwdGgiXV09PSJFbmRvdGhlbGlhICg1KSIpXSAtLT4KPCEtLSBkZWNfZW5kbzUgPC0gbW9kZWxHZW5lVmFyKGVuZG81X21pbG8pIC0tPgo8IS0tIGVuZG81X2h2Z3MgPC0gZ2V0VG9wSFZHcyhkZWNfZW5kbzUsIG49MTAwMCkgLS0+Cgo8IS0tIHBlcmNfZXhwcl9tYXQgPC0gc2FwcGx5KGVuZG81X2h2Z3MsIGZ1bmN0aW9uKHgpIC5jYWxjdWxhdGVfbmhvb2RfcGVyY19leHByZXNzaW9uKGxpdmVyX21pbG8sIGVuZG81X25ob29kcywgeCkpIC0tPgoKPCEtLSBtaWxvX3Jlc19lbmRvNSA8LSBtaWxvX3Jlc1t3aGljaChtaWxvX3JlcyROaG9vZCAlaW4lIGVuZG81X25ob29kcyksXSAtLT4KCjwhLS0gZmNfY29yIDwtIGFwcGx5KHBlcmNfZXhwcl9tYXQsIDIsIGZ1bmN0aW9uKHgpIEhtaXNjOjpyY29ycih4LCBtaWxvX3Jlc19lbmRvNSRsb2dGQykkclsxLDJdKSAtLT4KPCEtLSBmY19jb3JfcHZhbCA8LSBhcHBseShwZXJjX2V4cHJfbWF0LCAyLCBmdW5jdGlvbih4KSBIbWlzYzo6cmNvcnIoeCwgbWlsb19yZXNfZW5kbzUkbG9nRkMpJFBbMSwyXSkgLS0+Cgo8IS0tIGNvcl9mZWF0cyA8LSBuYW1lcyh3aGljaChhYnMoZmNfY29yKSA+IDAuNiAmIGFicyhmY19jb3JfcHZhbCkgPCAwLjA1KSkgLS0+CjwhLS0gY29yX2ZlYXRzX29yZGVyZWQgPC0gY29yX2ZlYXRzW29yZGVyKGZjX2Nvcltjb3JfZmVhdHNdKV0gLS0+Cgo8IS0tIHBsX2RmIDwtIGRhdGEuZnJhbWUocGVyY19leHByX21hdFssY29yX2ZlYXRzXSkgJT4lIC0tPgo8IS0tICAgcm93bmFtZXNfdG9fY29sdW1uKCJOaG9vZCIpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShOaG9vZD1hcy5kb3VibGUoTmhvb2QpKSAlPiUgLS0+CjwhLS0gICBsZWZ0X2pvaW4obWlsb19yZXMpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShsb2dGQ19yYW5rPXJhbmsobG9nRkMpKSAgLS0+Cgo8IS0tIHBsX3RvcCA8LSBwbF9kZiAlPiUgLS0+CjwhLS0gICAgIG11dGF0ZShpc19zaWduaWYgPSBpZmVsc2UoU3BhdGlhbEZEUiA8IDAuMSwgIlNwYXRpYWxGRFIgPCAwLjEiLCBOQSkpICU+JSAtLT4KPCEtLSAgICAgZ2dwbG90KGFlcyhsb2dGQ19yYW5rLCBsb2dGQykpICsgLS0+CjwhLS0gICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsgLS0+CjwhLS0gICAgIGdlb21fcG9pbnQoc2l6ZT0wLjIpICsgLS0+CjwhLS0gICAgIGdlb21fcG9pbnQoZGF0YT0uJT4lIGZpbHRlcighaXMubmEoaXNfc2lnbmlmKSksIGFlcyhjb2xvcj1pc19zaWduaWYpLCBzaXplPTAuNSkgKyAtLT4KPCEtLSAgICAgdGhlbWVfYncoKSArIC0tPgo8IS0tICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPSJyZWQiLCBuYW1lPSIiKSArIC0tPgo8IS0tICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpIC0tPgoKPCEtLSBwbF9ib3R0b20gPC0gcGxfZGYgJT4lIC0tPgo8IS0tICAgcGl2b3RfbG9uZ2VyKGNvbHM9c3RyX3JlcGxhY2UoY29yX2ZlYXRzX29yZGVyZWQsICItIiwgIi4iKSwgbmFtZXNfdG89J2ZlYXR1cmUnLCB2YWx1ZXNfdG89InBlcmNfZXhwcmVzc2VkIikgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGZlYXR1cmU9ZmFjdG9yKGZlYXR1cmUsIGxldmVscz1zdHJfcmVwbGFjZShjb3JfZmVhdHNfb3JkZXJlZCwgIi0iLCAiLiIpKSkgJT4lIC0tPgo8IS0tICAgZ2dwbG90KGFlcyhsb2dGQ19yYW5rLCBmZWF0dXJlLCBmaWxsPXBlcmNfZXhwcmVzc2VkKSkgKyAgLS0+CjwhLS0gICBnZW9tX3RpbGUoKSArIC0tPgo8IS0tICAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uPSJtYWdtYSIpICsgLS0+CjwhLS0gICB0aGVtZV9jbGVhcigpIC0tPgoKPCEtLSAocGxfdG9wIC8gcGxfYm90dG9tKSArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEsMikpIC0tPgo8IS0tIGBgYCAtLT4KCgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyMgUnVuIGNvbW1vbiBQQ0EgLS0+CjwhLS0gbWVyZ2VkX2NudHMgPC0gY2JpbmQobmhvb2RFeHByZXNzaW9uKGVuZG9fbWlsbyksIGxvZ2NvdW50cyhlbmRvX21pbG8pW2h2Z3MsXSkgLS0+CjwhLS0gbWVyZ2VkX2NudHNfc2NhbGVkIDwtIHQoc2NhbGUodChtZXJnZWRfY250cykpKSAtLT4KPCEtLSBtZXJnZWRfcGNhIDwtIEJpb2NTaW5ndWxhcjo6cnVuUENBKHQobWVyZ2VkX2NudHNfc2NhbGVkKSwgcmFuaz0zMCwgY2VudGVyPUZBTFNFKSAtLT4KPCEtLSBwY2FfbWF0IDwtIHJiaW5kKG1lcmdlZF9wY2EkeFsobmNvbChlbmRvX21pbG8pKzEpOihuY29sKGVuZG9fbWlsbykrKGxlbmd0aChuaG9vZHMoZW5kb19taWxvKSkpKSxdLCBtZXJnZWRfcGNhJHhbY29sbmFtZXMoZW5kb19taWxvKSxdKSAtLT4KPCEtLSAjIyBBZGQgdG8gc2xvdCBuaG9vZHNSZWR1Y2VkRGltIC0tPgo8IS0tIG5ob29kUmVkdWNlZERpbShlbmRvX21pbG8sICJQQ0EiKSA8LSBwY2FfbWF0IC0tPgoKPCEtLSAjIyBSdW4gVU1BUCBvbiBqb2ludCBQQ0EgLS0+CjwhLS0gdW1hcF9vdXQgPC0gdXdvdDo6dW1hcChuaG9vZFJlZHVjZWREaW0oZW5kb19taWxvLCAiUENBIiksIG5fbmVpZ2hib3JzID0gMjAsIG5fY29tcG9uZW50cyA9IDIsIHNjYWxlPUZBTFNFKSAtLT4KPCEtLSBjb2xuYW1lcyh1bWFwX291dCkgPC0gYygiVU1BUF8xIiwgIlVNQVBfMiIpIC0tPgo8IS0tIG5ob29kUmVkdWNlZERpbShlbmRvX21pbG8sICJVTUFQIikgPC0gdW1hcF9vdXQgLS0+Cgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIHNwbGl0X2J5PU5VTEwgLS0+CjwhLS0gIyMgSm9pbiB0ZXN0IHJlc3VsdHMgYW5kIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbnMgLS0+CjwhLS0gcmRpbV9kZiA8LSBkYXRhLmZyYW1lKG5ob29kUmVkdWNlZERpbShlbmRvX21pbG8sICJVTUFQIilbLGMoMSwyKV0pIC0tPgo8IS0tIGNvbG5hbWVzKHJkaW1fZGYpIDwtIGMoJ1gnLCdZJykgLS0+Cgo8IS0tIG5fbmhvb2RzIDwtIGxlbmd0aChuaG9vZHMoZW5kb19taWxvKSkgLS0+CjwhLS0gcmRpbV9kZlssIk5ob29kIl0gPC0gaWZlbHNlKDE6bnJvdyhyZGltX2RmKSAlaW4lIGMoMTpuX25ob29kcyksIGMoMTpuX25ob29kcyksIE5BKSAtLT4KPCEtLSB2aXpfZGYgIDwtIGxlZnRfam9pbihyZGltX2RmLCBtaWxvX3Jlc1t3aGljaChtaWxvX3JlcyRhbm5vdGF0aW9uX2xpbmVhZ2U9PSJFbmRvdGhlbGlhIiksXSwgYnk9Ik5ob29kIikgLS0+CjwhLS0gdml6X2RmW1sibmhJbmRleCJdXSA8LSB1bmxpc3QoaWZlbHNlKCFpcy5uYSh2aXpfZGYkTmhvb2QpLCBuaG9vZEluZGV4KGVuZG9fbWlsbylbdml6X2RmJE5ob29kXSxOQSkpIC0tPgo8IS0tIHZpel9kZltpcy5uYSh2aXpfZGZbIm5oSW5kZXgiXSksJ25oSW5kZXgnXSA8LSAxOm5jb2woZW5kb19taWxvKSAjIEFkZCBpbmRleCBhbHNvIHRvIHNpbmdsZS1jZWxscyAtLT4KCjwhLS0gaWYgKCFpcy5udWxsKHNwbGl0X2J5KSl7IC0tPgo8IS0tICAgc3BsaXRfZGYgPC0gZGF0YS5mcmFtZShzcGxpdF9ieT1jb2xEYXRhKGVuZG9fbWlsbylbLHNwbGl0X2J5XSkgLS0+CjwhLS0gICBzcGxpdF9kZlssIm5oSW5kZXgiXSA8LSAxOm5yb3coc3BsaXRfZGYpIC0tPgo8IS0tICAgdml6X2RmICA8LSBsZWZ0X2pvaW4odml6X2RmLCBzcGxpdF9kZiwgYnk9Im5oSW5kZXgiKSAtLT4KPCEtLSB9IC0tPgoKPCEtLSBmaWx0ZXJfYWxwaGE9MC4xIC0tPgo8IS0tICMjIEZpbHRlciBzaWduaWZpY2FudCBEQSBuaG9vZHMgLS0+CjwhLS0gaWYgKCFpcy5udWxsKGZpbHRlcl9hbHBoYSkpIHsgLS0+CjwhLS0gICBpZiAoZmlsdGVyX2FscGhhID4gMCkgeyAtLT4KPCEtLSAgICAgdml6X2RmIDwtIG11dGF0ZSh2aXpfZGYsIGxvZ0ZDID0gaWZlbHNlKFNwYXRpYWxGRFIgPiBmaWx0ZXJfYWxwaGEsIE5BLCBsb2dGQykpIC0tPgo8IS0tICAgfSAtLT4KPCEtLSB9IC0tPgoKPCEtLSAjIyBQbG90IC0tPgo8IS0tIHB0X3NpemU9MSAtLT4KPCEtLSBuaG9vZF9yZWR1Y2VkX2RpbXM9IlVNQVAiIC0tPgo8IS0tIGNvbXBvbmVudHM9YygxLDIpIC0tPgo8IS0tICAgcGwgPC0gLS0+CjwhLS0gICAgIGdncGxvdChkYXRhID0gYXJyYW5nZSh2aXpfZGYsIGFicyhsb2dGQykpLCAtLT4KPCEtLSAgICAgICAgICAgIGFlcyhYLCBZKSkgKyAtLT4KPCEtLSAgICAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSAnJyksIHNpemUgPSBwdF9zaXplIC8gMywgYWxwaGEgPSAwLjUpICsgLS0+CjwhLS0gICAgIGdlb21fcG9pbnQoIC0tPgo8IS0tICAgICAgIGRhdGEgPSAuICU+JSBmaWx0ZXIoIWlzLm5hKFNwYXRpYWxGRFIpKSwgLS0+CjwhLS0gICAgICAgYWVzKGZpbGwgPSBsb2dGQyksIC0tPgo8IS0tICAgICAgIHNpemUgPSBwdF9zaXplLCAtLT4KPCEtLSAgICAgICBzdHJva2UgPSAwLjEsIC0tPgo8IS0tICAgICAgICMgY29sb3VyPSJibGFjayIsIC0tPgo8IS0tICAgICAgIHNoYXBlID0gMjEgLS0+CjwhLS0gICAgICkgKyAtLT4KPCEtLSAgICAgc2NhbGVfZmlsbF9ncmFkaWVudDIoIC0tPgo8IS0tICAgICAgIG1pZHBvaW50ID0gMCwgLS0+CjwhLS0gICAgICAgaGlnaCA9ICJyZWQiLCAtLT4KPCEtLSAgICAgICBsb3cgPSAiYmx1ZSIsIC0tPgo8IS0tICAgICAgIG5hbWUgPSAibG9nLUZDIiAtLT4KPCEtLSAgICAgKSArIC0tPgo8IS0tICAgICB4bGFiKHBhc3RlKG5ob29kX3JlZHVjZWRfZGltcywgY29tcG9uZW50c1sxXSwgc2VwPSJfIikpICsgLS0+CjwhLS0gICAgIHlsYWIocGFzdGUobmhvb2RfcmVkdWNlZF9kaW1zLCBjb21wb25lbnRzWzJdLCBzZXA9Il8iKSkgLS0+Cgo8IS0tICAgaWYgKCFpcy5udWxsKHNwbGl0X2J5KSkgeyAtLT4KPCEtLSAgICAgcGwgPC0gcGwgKyBmYWNldF93cmFwKHNwbGl0X2J5fi4pIC0tPgo8IS0tICAgfSAtLT4KPCEtLSAgIGlmICghaXMubnVsbChmaWx0ZXJfYWxwaGEpKSB7IC0tPgo8IS0tICAgICBwbCA8LSBwbCArIC0tPgo8IS0tICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAnZ3JleScsIGxhYmVsID0gcGFzdGUoIlNwYXRpYWxGRFIgPiIsIHJvdW5kKGZpbHRlcl9hbHBoYSwgMikpKSArIC0tPgo8IS0tICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQoIC0tPgo8IS0tICAgICAgICAgJycsIC0tPgo8IS0tICAgICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdCggLS0+CjwhLS0gICAgICAgICAgIHNoYXBlID0gMjEsIC0tPgo8IS0tICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCAtLT4KPCEtLSAgICAgICAgICAgZmlsbCA9ICJncmV5NTAiLCAtLT4KPCEtLSAgICAgICAgICAgc2l6ZSA9IHB0X3NpemUsIC0tPgo8IS0tICAgICAgICAgICBhbHBoYSA9IDEsIC0tPgo8IS0tICAgICAgICAgICBzdHJva2UgPSAwLjEgLS0+CjwhLS0gICAgICAgICApIC0tPgo8IS0tICAgICAgICkpIC0tPgo8IS0tICAgfSBlbHNlIHsgLS0+CjwhLS0gICAgIHBsIDwtIHBsICsgLS0+CjwhLS0gICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICdncmV5JykgKyAtLT4KPCEtLSAgICAgICBndWlkZXMoY29sb3I9Im5vbmUiKSAtLT4KPCEtLSAgIH0gLS0+Cgo8IS0tICAgcGwgPC0gcGwgKyAtLT4KPCEtLSAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKyAtLT4KPCEtLSAgICAgdGhlbWUoIC0tPgo8IS0tICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIC0tPgo8IS0tICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgLS0+CjwhLS0gICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkgLS0+CjwhLS0gICAgICkgLS0+CjwhLS0gcGwgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZW5kb19taWxvIDwtIHNjYXRlcjo6cnVuUENBKGVuZG9fbWlsbywgc3Vic2V0X3Jvdz1odmdzKSAtLT4KPCEtLSBgYGAgLS0+CgoKCjwhLS0gLS0tIC0tPgo8IS0tICMjIE9sZCAoYmVmb3JlIEkgZ290IGRhdGFzZXQgZnJvbSBhdXRob3JzKSAtLT4KCjwhLS0gVXNpbmcgZGF0YSBmcm9tIFtSYW1hY2hhbmRyYW4gZXQgYWwuIDIwMTldKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNTg2LTAxOS0xNjMxLTMjU2VjMSkgKEdFTyBhY2Nlc3NpaW9uOiBHU0UxMzYxMDMpLiAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBodW1hbl9maWxlcyA8LSBsaXN0LmZpbGVzKCJ+L0Rvd25sb2Fkcy9HU0UxMzYxMDNfUkFXIiwgcGF0dGVybj0iR1NNNDA0MTEuLl9oZWFsdGh5fGNpcnJob3RpYyIsIGZ1bGwubmFtZXMgPSBUUlVFKSAgLS0+Cgo8IS0tIHByZWZpeGVzIDwtIHN0cl9yZW1vdmUoaHVtYW5fZmlsZXMsICJiYXJjb2Rlcy50c3YuZ3p8Z2VuZXMudHN2Lmd6fG1hdHJpeC5tdHguZ3oiKSAlPiUgLS0+CjwhLS0gICAjIHN0cl9yZW1vdmUoIi4rLyIpICU+JSAtLT4KPCEtLSAgIHVuaXF1ZSgpICAtLT4KCjwhLS0gc2NlX2xzIDwtIGxhcHBseShwcmVmaXhlcywgZnVuY3Rpb24oeCkgcmVhZDEweENvdW50cyh4LCB0eXBlPSJwcmVmaXgiKSkgLS0+CjwhLS0gbGl2ZXJfc2NlIDwtIHB1cnJyOjpyZWR1Y2Uoc2NlX2xzLCBjYmluZCkgLS0+Cgo8IS0tICMjIE1ha2UgY29sRGF0YSBpbmZvIC0tPgo8IS0tIG5ld19jb2xkYXRhIDwtIGNvbERhdGEobGl2ZXJfc2NlKSAlPiUgLS0+CjwhLS0gICBkYXRhLmZyYW1lKCkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKFNhbXBsZT1zdHJfcmVtb3ZlKFNhbXBsZSwgIi4rLyIpICU+JSBzdHJfcmVtb3ZlKCJfJCIpKSAlPiUgLS0+CjwhLS0gICBzZXBhcmF0ZShTYW1wbGUsIGludG89YygiY29sMSIsICJQYXRpZW50IiwgIlNvcnQiKSwgc2VwID0gIl8iLCByZW1vdmU9RkFMU0UpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoQ29uZGl0aW9uPXN0cl9yZW1vdmUoUGF0aWVudCwgIi4kIikpICU+JSAtLT4KPCEtLSAgIHNlbGVjdCgtY29sMSkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKENlbGxfaWQgPSBzdHJfYyhTYW1wbGUsICJfIixCYXJjb2RlKSkgJT4lIC0tPgo8IS0tICAgY29sdW1uX3RvX3Jvd25hbWVzKCJDZWxsX2lkIikgLS0+Cgo8IS0tIGNvbG5hbWVzKGxpdmVyX3NjZSkgPC0gcm93bmFtZXMobmV3X2NvbGRhdGEpIC0tPgo8IS0tIGNvbERhdGEobGl2ZXJfc2NlKSA8LSBEYXRhRnJhbWUobmV3X2NvbGRhdGEpIC0tPgoKPCEtLSAjIHNhdmVSRFMobGl2ZXJfc2NlLCAifi9HU0UxMzYxMDNfU2luZ2xlQ2VsbEV4cGVyaW1lbnQuUkRTIikgLS0+CjwhLS0gYGBgIC0tPgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBsaXZlcl9zY2UgPC0gcmVhZFJEUygifi9HU0UxMzYxMDNfU2luZ2xlQ2VsbEV4cGVyaW1lbnQuUkRTIikgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBRQyBtZXRyaWNzIHNob3cgdGhhdCB0aGUgb3V0bGllciBjZWxscyBhcmUgYWxyZWFkeSBmaWx0ZXJlZCAoZm9sbG93aW5nIFt0aGlzXShodHRwczovL29zY2EuYmlvY29uZHVjdG9yLm9yZy9vdmVydmlldy5odG1sI2RhdGEtcHJvY2Vzc2luZy1hbmQtZG93bnN0cmVhbS1hbmFseXNpcykpIC0tPgoKPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9OH0gLS0+CjwhLS0gIyBpcy5taXRvIDwtIGdyZXBsKCJeTVQtIiwgcm93bmFtZXMobGl2ZXJfc2NlKSkgLS0+CjwhLS0gcWNzdGF0cyA8LSBwZXJDZWxsUUNNZXRyaWNzKGxpdmVyX3NjZSkgLS0+Cgo8IS0tIGNvbERhdGEobGl2ZXJfc2NlKSA8LSBjYmluZChjb2xEYXRhKGxpdmVyX3NjZSksIHFjc3RhdHMpIC0tPgoKPCEtLSBwbG90Q29sRGF0YShsaXZlcl9zY2UsIHg9IlNhbXBsZSIsIHkgPSAidG90YWwiLCBvdGhlcl9maWVsZHMgPSAiQ29uZGl0aW9uIikgKyAtLT4KPCEtLSAgIHNjYWxlX3lfbG9nMTAoKSArIC0tPgo8IS0tICAgZmFjZXRfd3JhcCh+Q29uZGl0aW9uLCBzY2FsZXMgPSAiZnJlZSIpICsgLS0+CjwhLS0gICBnZ3RpdGxlKCJ0b3RhbCBjb3VudHMiKSAgLS0+Cgo8IS0tIHBsb3RDb2xEYXRhKGxpdmVyX3NjZSwgeD0iU2FtcGxlIiwgeSA9ICJkZXRlY3RlZCIsIG90aGVyX2ZpZWxkcyA9ICJDb25kaXRpb24iKSArIC0tPgo8IS0tICAgZmFjZXRfd3JhcCh+Q29uZGl0aW9uLCBzY2FsZXMgPSAiZnJlZSIpICsgLS0+CjwhLS0gICBnZ3RpdGxlKCJEZXRlY3RlZCBnZW5lcyIpICAtLT4KCjwhLS0gYGBgIC0tPgoKPCEtLSAjIyMgTm9ybWFsaXphdGlvbiAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGxpYl9zZiA8LSBsaWJyYXJ5U2l6ZUZhY3RvcnMobGl2ZXJfc2NlKSAtLT4KPCEtLSBoaXN0KGxvZzEwKGxpYl9zZiksIHhsYWI9IkxvZzEwW1NpemUgZmFjdG9yXSIsIGNvbD0nZ3JleTgwJykgLS0+CjwhLS0gYGBgIC0tPgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBzZXQuc2VlZCgxMDApIC0tPgo8IS0tIGxpdmVyX3NjZSA8LSBsb2dOb3JtQ291bnRzKGxpdmVyX3NjZSkgLS0+CjwhLS0gYXNzYXlOYW1lcyhsaXZlcl9zY2UpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gIyMjIEZlYXR1cmUgc2VsZWN0aW9uIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbGlicmFyeShzY3JhbikgLS0+CjwhLS0gZGVjX2xpdmVyIDwtIG1vZGVsR2VuZVZhcihsaXZlcl9zY2UpIC0tPgoKPCEtLSAjIFZpc3VhbGl6aW5nIHRoZSBmaXQ6IC0tPgo8IS0tIGZpdF9saXZlciA8LSBtZXRhZGF0YShkZWNfbGl2ZXIpIC0tPgo8IS0tIHBsb3QoZml0X2xpdmVyJG1lYW4sIGZpdF9saXZlciR2YXIsIHhsYWI9Ik1lYW4gb2YgbG9nLWV4cHJlc3Npb24iLCAtLT4KPCEtLSAgICAgeWxhYj0iVmFyaWFuY2Ugb2YgbG9nLWV4cHJlc3Npb24iKSAtLT4KCjwhLS0gaHZncyA8LSBnZXRUb3BIVkdzKGRlY19saXZlciwgbj0zMDAwKSAtLT4KPCEtLSBgYGAgLS0+CgoKCjwhLS0gIyMjIERpbSByZWR1Y3Rpb24gLS0+Cgo8IS0tIGBgYHtyLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTR9IC0tPgo8IS0tIGxpdmVyX3NjZSA8LSBzY2F0ZXI6OnJ1blBDQShsaXZlcl9zY2UsIHN1YnNldF9yb3c9aHZncywgbmNvbXBvbmVudHM9MzApIC0tPgo8IS0tIHJlZHVjZWREaW0obGl2ZXJfc2NlLCAiUENBIikgPC0gcmVkdWNlZERpbShsaXZlcl9zY2UsICJQQ0EiKVssMToxMV0gLS0+CjwhLS0gcGxvdFBDQShsaXZlcl9zY2UsIGNvbG91cl9ieT0iQ29uZGl0aW9uIiwgbmNvbXBvbmVudHM9MykgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0gLS0+CjwhLS0gbGl2ZXJfc2NlIDwtIHJ1blVNQVAobGl2ZXJfc2NlLCBkaW1yZWQ9IlBDQSIsIG5jb21wb25lbnRzPTIpIC0tPgoKPCEtLSBzY2F0ZXI6OnBsb3RVTUFQKGxpdmVyX3NjZSwgY29sb3VyX2J5PSJDb25kaXRpb24iLCBwb2ludF9hbHBoYT0xLCAgcG9pbnRfc2l6ZT0wLjgpICAtLT4KPCEtLSBzY2F0ZXI6OnBsb3RVTUFQKGxpdmVyX3NjZSwgY29sb3VyX2J5PSJTb3J0IiwgcG9pbnRfYWxwaGE9MC4zLCAgcG9pbnRfc2l6ZT0wLjUpIC0tPgo8IS0tIHNjYXRlcjo6cGxvdFVNQVAobGl2ZXJfc2NlLCBjb2xvdXJfYnk9IlBhdGllbnQiLCBwb2ludF9hbHBoYT0wLjMsICBwb2ludF9zaXplPTAuNSkgLS0+CjwhLS0gYGBgIC0tPgo8IS0tIGBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9IC0tPgo8IS0tIHJvd25hbWVzKGxpdmVyX3NjZSkgPC0gcm93RGF0YShsaXZlcl9zY2UpJFN5bWJvbCAtLT4KPCEtLSBzY2F0ZXI6OnBsb3RVTUFQKGxpdmVyX3NjZSwgY29sb3VyX2J5PSJDRDNEIiwgcG9pbnRfYWxwaGE9MC4zLCBwb2ludF9zaXplPTAuNSkgLS0+CjwhLS0gYGBgIC0tPgoKCgo=